1 Introduction

1) Why this topic

With the development of Internet and signal techniques, smartphone plays an essential role in people’s life. Ten years ago, people only used mobile to text and make phone calls, but nowadays smartphones can do all kinds of stuff, such as surfing the internet, sending the emails, video chatting with friends or even paying bills etc. So, we want to see how popular mobile is in different countries and what patterns of internet request by mobile across time in one day are. Also, the mobile operators can get the locations of the users when they make requests, but with some signal uncertainty, it is also worthy to study the geo-location information and see the spatial patterns of signal accuracy.

In this project, we will focus on some specific areas in the world. The middle east countries are all close to each other while they have very different national conditions. Russia has vast territory so the mobile signal may vary across the country. The study of these two areas may produce very interesting results so we used mobile request data from these countries to exam the use of mobile and signal geo-location information in Middle East and Russian.

We used the data visualization and statistical method to understand mobile popularity and signal accuracy in different countries, found the underlying reason of different popularity and accuracy. In addition, we also developed a mobile signal tracking site called Mobile Signal. It lists mobile usage records across time for three days in a row both in Middle East and Russia as well as tools and information needed to be able to have a comprehensive understanding of the variations across countries or areas respectively.

2) Research Questions

From the data, we try to figure out four questions in popularity of mobile:
a. Number of mobile users in different countries
b. Prevalence of mobile internet usage in different countries
c. Development of mobile industry in different countries
d. Usage volume of mobile across time in one day

Also with this data, we can study more interesting topics using geo-location information:
a. Pattern of signal accuracy in different Mideast countries across time
b. The movement pattern of mobile internet request of some specific groups of people

3) How to find the data

The data was from Zhirui Wang’s intern company. It contains data of three days in 2016 from middle east countries and Russia. The original data is 17.6G. We upload them to Google Drive. We also used data from World Population and GDP data from World Bank.

2 Team members and distributed contributions

We have four group members: Zhirui Wang (zw2389), Xikai Chen (xc2358), Yaqing Wang (yw2902) and Chang Pan (cp2923). To start, Zhirui did all data cleaning, and plotted barcharts to visualize the number of records and accuracy. Yaqing then did analysis on the barcharts in order to get a basic idea of the dataset. Further, Zhirui made spatial visualizations of ego-location data in R to generate two maps: the number of records in Middle East and Russia. After the basic steps, Xikai created a shiny App and embedded Zhirui’s plots and maps in the app. He and Chang also managed to use animations to visualize the changes of dots in the maps over time. In addition, they optimized the app to enable filters to capture mobile usages in specific landmarks in Russia. At last, for the report, Yaqing is responsible for Introduction, Team and Middle East part of Main Analysis, Zhirui is responsible for Analysis of Data Quality, Russia part of Main Analysis, and Chang and Xikai are responsible for Executive Summary.

3 Data Quality

This is a data set of mobile signal data. It consists of two parts, the first part is from 22 countries in the Middle East during Dec 10-13 2016, and the second part is from Russia during Dec 10-12. First let us look at the data quality of the Mideast data:

The original data of Mideast has 1.93 Gigabytes, it has no column names and is tab delimited. The columns of the data are: Timestamp, IP Address, User ID, Latitude, Longitude, Accuracy, Country. The time stamp has precision to the second, while we will mostly focus on the analysis on the hour basis so we will convert it into hours later. The IP Address actually does not give much information under our analysis purpose, we will drop this variable to keep a smaller consumption of memory. The User ID is unique for every mobile phone, in the analysis of Mideast, we mainly focus on country level, so the User ID is also not informative, we will drop this column as well. Also, due to the country level analysis, the longitude and latitude is useless as long as we have the country name column, we will also drop the longitude and latitude here. The accuracy is a measure of the ‘confidence interval’ that how far the recorded location information might differ from the actual location. When we open Google map, there will be a somewhat transparent sky blue circle around our location, and the radius of that circle is the accuracy here. Maybe it is better to call it ‘inaccuracy’ because the larger the number, the less the confidence we have about the actual location. But in my company called it ‘accuracy’ so let us just keep this way. The final column is the country of the mobile phone. It is an ISO two letter abbreviation of each country, so we have to web-scrape a code book to convert the abbreviation into actual country name. The data cleaning function is as following:

library(rvest)
codebook <- 'http://www.worldatlas.com/aatlas/ctycodes.htm' %>% 
  read_html %>% 
  html_nodes('table') %>% 
  .[[1]] %>% 
  html_table()

CleanData_Mideast <- function(input,output){
  library(tidyverse)
  x <- read_delim(input,
    "\t", escape_double = FALSE, col_names = FALSE,
    trim_ws = TRUE)
  colnames(x) <- c('Timestamp','IP Address','User ID','Latitude','Longitude','Accuracy','Country')
  x$COUNTRY <- codebook$COUNTRY[match(x$Country,codebook$`A2 (ISO)`)]
  x <- x %>% select(Timestamp,Accuracy,COUNTRY)
  write_csv(x,output)
}
CleanData_Mideast("C:/Users/wang_/Desktop/2016-12-11a.txt","C:/Users/wang_/Desktop/2016-12-11a_new.csv")
CleanData_Mideast("C:/Users/wang_/Desktop/2016-12-12a.txt","C:/Users/wang_/Desktop/2016-12-12a_new.csv")
CleanData_Mideast("C:/Users/wang_/Desktop/2016-12-13a.txt","C:/Users/wang_/Desktop/2016-12-13a_new.csv")

Then let us look at the data of Russia:

The original data of Russia has 15.6 Gigabytes, it is also tab delimited and has no column names. The columns of the data are Time Stamp, IP Address, User ID, Latitude, Longitude, Accuracy, Wi-Fi Networks Nearby, GSM Towers, Country. The Time Stamp, IP address and Accuracy are the same as the data of Mideast, we will remain the same processing method as in the Mideast part. In this part of analysis, we will focus on individual level, so the User ID, Latitude and Longitude information is very crucial, we will not drop them as in the previous part. The Wi-Fi Networks Nearby, GSM Towers and Country does not provide useful information for us to analyze, we will drop them. Thus, the code for cleaning the data is as follow:

CleanData_Russia <- function(input,output){
  library(tidyverse)
  x <- read_delim(input,
                  "\t", escape_double = FALSE, col_names = FALSE,
                  trim_ws = TRUE)
  colnames(x) <- c('Time Stamp','IP Address','User ID','Latitude','Longitude','Accuracy','Wifi Networks Nearby','GSM Towers','Country')
  x <- x %>% select(`Time Stamp`,`User ID`,`Latitude`,`Longitude`,`Accuracy`)
  write_csv(x,output)
}
CleanData_Russia("C:/Users/wang_/Desktop/2016-12-10b.txt","C:/Users/wang_/Desktop/2016-12-10b_new.csv")
CleanData_Russia("C:/Users/wang_/Desktop/2016-12-11b.txt","C:/Users/wang_/Desktop/2016-12-11b_new.csv")
CleanData_Russia("C:/Users/wang_/Desktop/2016-12-12b.txt","C:/Users/wang_/Desktop/2016-12-12b_new.csv")

The data is the records from telecom company, they by nature have no missing value or outliers. However, there are records that do not belong to one day appear in the data of that day. In the analysis process, we will do the data cleaning process to drop all these rows.

We have integrated the first 1000 rows of data from each day in Mideast and Russia into our shiny app under the data tab. The code of the shiny app is on the Github.

4 Executive Summary

Mobile usage is an appealing topic. On the micro aspect, studying one’s internet request records can help us know about one’s living circle, lifestyle and etc,. on the macro aspect, analyzing people’s mobile request data as well as mobile signal accuracy reveals a lot about the country’s development, level of wealth, or even the countries’ infrastructure development.

In this project, we focus on some specific areas in the world. The middle east countries are all close to each other while they have very different national conditions. Russia has vast territory so the mobile signal may vary across the country. The study of these two areas obtains some interesting results, and we are going to present some revealing findings in this short summary.

First, we took a look at Middle East countries. Here is simply a plot showing the number of mobile usage records in different countries.

From the plot above we can see that Turkey, Saudi Arabia and United Arab Emirates have the highest number of records, approaching 1.5 million. All of these three countries rank the top in the Middle East Total GDP Ranking list, so it makes sense that these countries have the largest numbers of active mobile users. In general, the smaller or the poorer countries tend to have fewer records. However, the number of records in small countries like Cyprus is more than four times of that in large countries like Iran, which is totally unexpected.

However, given the uniqueness of Cyprus, it make sense. As a small island country with great tourism resources, Cyprus has tourists from nearby countries all year around. People love to go there for little breaks. Especially for Europeans, Cyprus is just a short-flight away, and has much lower living expense than most European countries and other Mideast tourism countries like United Arab Emirates. Therefore it is highly possible that a large portion of the number of records comes from foreign tourists.

In addition, since Cyprus is a small island country which do not have much potential for agriculture or industry, it is reasonable to suggest that mobile industry has a higher relative development in Cyprus than in other Middle East countries, which is consistent with the earlier reasoning that Cyprus have prosperous tourism. However, there are still other possible explanations for this pattern. For example, the data itself might come from a single carrier, which could be based in Cyprus. Then, the huge volume of records in Cyprus would make more sense, since in other countries, people may use other major carriers and such great number of records is invisible in this dataset.

Besides the number of records, the other interesting feature in this data set is the accuracy. It is a measure of the ‘confidence interval’ that the recorded location information differs from the actual one. So actually the larger the value is, the less confidence we have about the location.

From the plot above, there are four countries have mean accuracy over 2000 meters: Libya, Iraq, South Sudan and Democratic Republic of Congo. All of them are in upheaval or experienced huge turbulence. By search on the internet, we notice that the smoke from the wars also affect the mobile signal, hence, affect the accuracy. Additionally, in unstable countries like these, the base stations are easily getting damaged, and there is no extra money, people, resources or motivations for someone to develop the mobile industry, both mobile phones and base stations. So they are expected to have highest accuracy.

On the other hand, Cyprus again beats other countries to be the best in terms of accuracy in Middle East. Besides its stable political situation, the majority of the country is plain, which is beneficial for base stations. Furthermore, as a popular tourist destination, it has the motivation to build a better environment. For example, high quality infrastructures, for internet users in order to attract more tourists. In turn, tourist who probably come from richer countries would use high-quality cell phones. And all of these could lead to better accuracy.

Now, we move to Russia. Here, we made a closer look at the moving pattern of specific groups, and found some interesting patterns of tourist on Moscow in the map.

Take this plot as an example, the blue dots represent the positions of a certain person, which clearly reveal the moving pattern of the person. Since they all perfectly lined up with each other, it seems that the person was queuing in the line for a traveling sight or maybe just a restaurant. However, similar lining patterns were not everywhere in the map as it was supposed to be. People do not line up to purchase the tickets or wait to enter the sights, so it is safe for us to conclude that this period might not be during a busy traveling season in Moscow, and tourist could go wherever they want to visit without waiting a line.

Another finding is that many of the cluster of internet request is on a bridge or at the waterfront, this may be due to the fact that bridges and waterfront are great places for photography, people may take photos there using their mobile phones, and then upload onto the social media, which requires internet request.

To sum it up, in Middle East, the larger or the richer a country is, the more mobile usage records and better accuracy it has, with one exception: Cyprus. As a great tourism country, it attracts many foreign visitors, who make great contributions to the country’s mobile usage records and in turn bring high-tech smartphones to motivate Cyprus for better base stations. Also, as expected, countries in upheaval or even in war have fewer records and larger accuracy. As in Russia, based on the internet request showing in the map, we can conclude that it is highly likely a off-season for tourism in Moscow, and when people visit natural sights such as pond, they tend to use cell phones for internet more than often.

5 Main Analysis

Middle East

library(plotly)
library(tidyverse)
library(gganimate)
library(lubridate)
library(forcats)
library(biglm)
library(lmtest)
library(knitr)
library(leaflet)
X2016_12_11a_new <- read_csv("C:/Users/wang_/Desktop/2016-12-11a_new.csv",progress=F)
X2016_12_12a_new <- read_csv("C:/Users/wang_/Desktop/2016-12-12a_new.csv",progress=F)
X2016_12_13a_new <- read_csv("C:/Users/wang_/Desktop/2016-12-13a_new.csv",progress=F)
x <- bind_rows(X2016_12_11a_new,X2016_12_12a_new,X2016_12_13a_new)

Number of records

First we took a look at the number of records in each Middle East country. For the purpose of comparison, we have two options: barcharts and piecharts. However, with more than 20 countries in total, it is difficult to identify the slice for a country with small portion, or even compare it with a smaller slice using piecharts, therefore, we settled with barcharts.

x_group_count <- x %>% 
  filter(Timestamp>as.Date('2016-12-12 00:00:00 UTC')) %>% 
  group_by(COUNTRY) %>% 
  summarise(count=n()) %>% 
  arrange(count)
(x_group_count %>% 
  ggplot(aes(y=count,x=as_factor(COUNTRY)))+
  geom_bar(stat="identity",fill='skyblue2')+
  coord_flip()+
  ylab('Number of Records')+
  xlab('Country Name')+
  ggtitle('Number of Records by Country')) %>% 
  ggplotly

In order to draw this graph, first we filter the data to drop the rows that does not belong to these three days. Then we group the data by country and count the number of each country. We want the bar chart to be sorted by the number of records, so we arrange the count variable and use as_factor() function to remain this order when passing to ggplot. We also flip the coordinates for better visualization of the country names.

From the plot above, we can see that Turkey, Saudi Arabia and United Arab Emirates have the highest number of records, approaching 1.5 million. All of the three countries rank the top in the Middle East Total GDP Ranking list, so it makes sense that these countries have the largest numbers of active mobile users. In general, the smaller or the poorer countries tend to have fewer records. However, the number of records in small countries like Cyprus is more than four times of that in large countries like Iran.

There are two obvious factors associated with the number of records: national population and GDP, and we are going to explore them one by one. Here, we first start with population. By dividing the number of records by the national population, we obtain the proportion of the active users in the national population, which could be a measure of how prevalent mobile usage is in each country.

population <- "http://www.worldometers.info/world-population/population-by-country/" %>% 
  read_html %>% 
  html_nodes('table') %>% 
  .[[1]] %>% 
  html_table() %>% 
  .[,2:3]
colnames(population)[2] <- 'Population'
population$Population <- population$Population %>% gsub(',','',.) %>% as.numeric()
a <- match(x_group_count$COUNTRY,population$`Country (or dependency)`)
a[a %>% is.na %>% which] <- c(16,61,121,17)
x_group_count$Population <- population$Population[a]
(x_group_count %>% 
  mutate(percentage=100*count/Population) %>% 
  ggplot(aes(y=percentage,x=as_factor(COUNTRY)))+
  geom_bar(stat="identity",fill='skyblue2')+
  coord_flip()+
  ylab('Number of Records/Population')+
  xlab('Country Name')+
  ggtitle('Number of Records to Population by Country')) %>% 
  ggplotly

In order to draw this graph, we first scrape world population information from Internet, and then match the table onto our original data according to country name. We divide the number of records by the population and times 100 to get the percentage, then draw the graph use the same technique as the previous part. An alternative option is to use the number of unique ID as the numerator to get the percentage. However, we want the number of internet request each user made can also be included in this index, thus we choose to use the number of records to get the percentage.

We can know from the plot that Turkey, Saudi Arabia and United Arab Emirates do not rank the highest any more, instead Cyprus has an enormously larger number than other countries: nearly a half of the country population has made internet request in three days. We think this is because the fact that Cyprus is a small island country with great tourism resources. People from nearby countries love to go there for a little break, especially Europeans. So it is highly possible that the large number of records consist of great many of foreign tourists. Other than Cyprus, it seems that richer countries generally have more records per person than poorer ones.

To confirm this finding, we choose to examine the ratio of number of active users to the total GDP, which can be a measure of the relative development of mobile industry to the whole industry in each country. We find the total GDP data from world bank data set, and divide the number of records to total GDP.

url <- 'http://api.worldbank.org/v2/en/indicator/NY.GDP.MKTP.CD?downloadformat=csv'
temp <- tempfile()
download.file(url, temp, mode="wb")
unzip(temp, "API_NY.GDP.MKTP.CD_DS2_en_csv_v2.csv")
totalgdp <- read_csv("API_NY.GDP.MKTP.CD_DS2_en_csv_v2.csv",skip = 4)[,c(1,2,60)]
unlink(temp)
totalgdp$Country <- codebook$COUNTRY[match(totalgdp$`Country Code`,codebook$`A3 (UN)`)]
a <- match(x_group_count$COUNTRY,totalgdp$Country)
x_group_count$gdp <- totalgdp$`2015`[a]
(x_group_count %>% 
  mutate(percentage=count/gdp) %>% 
  ggplot(aes(y=percentage,x=as_factor(COUNTRY)))+
  geom_bar(stat="identity",fill='skyblue2')+
  coord_flip()+
  ylab('Number of Records/Total GDP')+
  xlab('Country Name')+
  ggtitle('Number of Records to Total GDP by Country')) %>% 
  ggplotly

In order to draw this graph, we first automatically download the GDP data from World Bank Open Data, use the same way as above to match it to the original data, and then divide the number of records by total GDP. An alternative option here is to use GDP per capita, and then we will get a measure of an Engel-coefficient-like index of the mobile phone usage. However here we want to focus on the country level analysis, so we just go with the relative development of mobile industry.

We can see that again Cyprus surpasses the other countries by a huge amount. Since it is a small island country which do not have much potential for agriculture or industry, it is reasonable to suggest that mobile industry has a higher relative development in Cyprus than in other Middle East countries, which is consistent with the earlier reasoning that Cyprus have prosperous tourism. However, there are still other possible explanations for this pattern, for example, the data itself might come from a single carrier, which could be based in Cyprus. Then, the huge volume of records in Cyprus would make more sense, since in other countries, people may use other major carriers and such great number of records is invisible in this dataset.

After comparing the data across countries, we now can compare them across time.

First, we want to see how the number of records varies across time, so we plot two animation interactive graphs that evolve as time goes by.

This is a screen shot of the interactive map(In shiny app, it is Number of Records in Mideast map tab):

We use leaflet to draw this Choropleths graph. We download geojson data of the world country polygons, use geojsonio::geojson_read() to read in the data as a SpatialPolygonsDataFrame object, and then concatenate our count data into this object. Because the value of number of records vary a lot across countries, we have to use uneven color bar to visualize the values. We add a slider selector to the graph, to select the hour of the data. We also make the graph animation, which controlled by a “play/pause” button. We use addPolygons() function to draw SpatialPolygonsDataFrame onto the map. We set many parameters in this function to make this graph more pretty, such as making the polygon transparent in order to see the country name in the background clearly, make country boundary white and dashed line in order to make it looks like hand-made, and add description of each country when the cursor are on that polygon.

This is a screen shot of the interactive barchart(In shiny app, it is Number of Records in Mideast barchart tab):

This graph is very similar to the static bar chart of the number of records, except we add another dimension of hour into this graph to make it animation. We also add a slider selector to the graph, to select the hour of the data and use filter() function to select the data of that hour, and then render the plot.

From the plot above, we can see that the number of records touch the bottom at dawn, start to increase as time goes by, and then reach the peak at midnight, which makes perfect sense. At dawn, there are few people still awake, while almost all people are asleep. Then, when people start to get up and begin the day, people start to use mobile for all kinds of things. However, in the daytime, people have to work, study or just run errands, so after they getting off work, finishing schoolwork for the day, having a great dinner with family, putting their children to bed, the mobile usage peak occurs.

Accuracy

Besides the number of records, the other interesting feature in this data set is the accuracy. It can be seen as the ‘confidence interval’ of the base stations in different countries, which can also be affected by the mobile device itself.

x_group_accuracy <- x %>% 
  filter(Timestamp>as.Date('2016-12-12 00:00:00 UTC')) %>% 
  group_by(COUNTRY) %>% 
  summarise(mean_Accuracy=mean(Accuracy),st_accuracy=sd(Accuracy))
(x_group_accuracy %>% 
  arrange(mean_Accuracy) %>% 
  ggplot(aes(y=mean_Accuracy,x=as_factor(COUNTRY)))+
  geom_bar(stat="identity",fill='skyblue2')+
  coord_flip()+
  ylab('Mean Accuracy')+
  xlab('Country Name')+
  ggtitle('Mean Accuracy by Country')) %>% 
  ggplotly

In order to draw this graph, first we filter the data to drop the rows that does not belong to these three days. Then we group the data by country and calculate the mean and standard deviation of accuracy of each country. We also sort the bar chart by the mean accuracy.

From the plot above, there are four countries have mean accuracy over 2000 meters: Libya, Iraq, South Sudan and Democratic Republic of Congo. All of them are in upheaval or experienced huge turbulence. The smoke from the wars could really affect the mobile signal, hence, affect the accuracy. Additionally, in unstable countries like these, there is no extra money, people, resources or motivations for someone to develop the mobile industry, both mobile phones and base stations. So they are expected to have highest accuracy. On the other hand, Cyprus again beats other countries to be the best in terms of accuracy in Middle East. Besides its stable political situation, the majority of the country is plain, which is beneficial for base stations. Furthermore, as a popular tourist destination, it has the motivation to build a better environment for internet users in order to attract more tourists.

Also we can visualize the mean accuracy change by time.

This is a screen shot of the interactive barchart(In shiny app, it is Mean Accuracy in Mideast barchart tab):

This graph is very similar to the static bar chart of the mean accuracy, except we add another dimension of hour into this graph to make it animation. We also add a slider selector to the graph, to select the hour of the data and use filter() function to select the data of that hour, and then render the plot.

It does not seem to be a clear pattern of how the mean accuracy evolve over time, but we can see that South Sudan and Libya varies a lot across time. So we plot the standard deviation of the accuracy across country and across time to have a more clear view.

(x_group_accuracy %>% 
  arrange(st_accuracy) %>% 
  ggplot(aes(y=st_accuracy,x=as_factor(COUNTRY)))+
  geom_bar(stat="identity",fill='skyblue2')+
  coord_flip()+
  ylab('Standard Deviation of Accuracy')+
  xlab('Country Name')+
  ggtitle('Standard Deviation of Accuracy by Country')) %>% 
  ggplotly

We use the data frame we generated from the previous part as input to plot this graph. We ordered the countries by the value of standard deviation of accuracy and draw the bar chart.

South Sudan has the highest standard deviation, followed by Libya and Syrian, which have much to do with their unstable political situations. However, the rest of countries have similarly high standard deviation. So it is possible that Middle East countries generally do not have sophisticated techniques and well-developed infrastructure, which leads to the poor accuracy with great standard deviation.

(x %>% 
  filter(Timestamp>as.Date('2016-12-12 00:00:00 UTC')) %>% 
  mutate(Hour=hour(Timestamp)) %>% 
  group_by(Hour) %>% 
  summarise(st_accuracy=sd(Accuracy)) %>% 
  mutate(hour=Hour %>% as.character) %>% 
  ggplot(aes(y=st_accuracy,x=hour %>% as_factor))+
  geom_bar(stat="identity",fill='skyblue2')+
  coord_flip()+
  ylab('Standard Deviation of Accuracy')+
  xlab('Hour')+
  ggtitle('Standard Deviation of Accuracy across Time')) %>% 
  ggplotly

In order to draw this graph, first we filter the data to drop the rows that does not belong to these three days. Then we group the data by hour and calculate the standard deviation of accuracy of each hour. We also have to use as_factor to maintain the numerical order of the hours, or in ggplot after we convert the hour into character, it will arrange 10, 11 and 12 after 1, not after 9.

From the earlier analysis on the number of records across time, we naturally assumed that the accuracy has the similar pattern. However, based on the plot above, there is really no significant difference in standard deviation of accuracy across time. So there is a strong indication that accuracy mainly depends on base stations itself other than how many people are using the mobile.

Russia

Number of Records and Accuracy

First we draw a bar chart of the number of records per hour

X2016_12_10b_new <- read_csv("C:/Users/wang_/Desktop/2016-12-10b_new.csv",progress=F)
X2016_12_11b_new <- read_csv("C:/Users/wang_/Desktop/2016-12-11b_new.csv",progress=F)
X2016_12_12b_new <- read_csv("C:/Users/wang_/Desktop/2016-12-12b_new.csv",progress=F)
x <- bind_rows(X2016_12_10b_new,X2016_12_11b_new,X2016_12_12b_new)
(x %>% 
  mutate(Hour=hour(`Time Stamp`)) %>% 
  group_by(Hour) %>% 
  summarise(count=n()) %>% 
  ggplot(aes(y=count,x=Hour %>% as.character))+
  geom_bar(stat="identity",fill='skyblue2')+
  coord_flip()+
  ylab('Number of Records')+
  xlab('Hour')+
  ggtitle('Number of Records across Time')) %>% 
  ggplotly

The graph plotting process is almost the similar to the counterpart in Mideast. The only difference is that there is no data that is not in that day, so we do not need to clean it first.

The internet usage behavior in Russia is very different from that in Mideast. The number of users peaks in the afternoon, decreases as time goes by and reaches the bottom at night, which is the opposite of the Mideast. It might be that Russians tend to start their day early, and finish their jobs around the noon. Then after the early lunch, they like to have some afternoon tea with colleagues or friends, where they chat, laugh, do selfies, post on social media like Facebook or Instagram. Also, Russians are kind of traditional, so after work or school, they tend to go home and have some quality time with families, like watching a movie together, reading books to children, or even taking a dance lesson with spouse etc.

We can also see this relationship when we plot that on the map. This is a screen shot of the animation map (In shiny app, it is Accuracy in Russia map tab):

In this graph we have billions of points to visualize, when we try to use interactive graphing to visualize it, the R will crash halfway, thus we have to use static graphing method to plot the map, and combine the map over time to make animation. Here we use ggmap package to draw the static map. The range of the Accuracy is very huge, so we use log-transformation on the Accuracy in order to get a more clear color visualization. It will took several minutes to draw a map for one of the ten hours, so we use parallel computing method in R to plot the map in parallel in order to plot the map faster. We save each map as png, and read each hour’s map in shiny using an hour slider selector.

As shown in the map, the mobile phone users are all clustered in the south east part of the country, but there is even no single request in most part of the Siberia. It is the same as we expected since the majority of Russians live in the Southeastern region, while Siberia is bare due to its unbearable weather.

Also, we can see the pattern discussed earlier clearly showing in the map: the number of dots peaks in the afternoon and decreases as time goes by.

In addition, we can see from the map that in the south east part of the country there are many red dots, while in the north east part most of the dots are light yellow. To quantify this statement, we can generate a linear regression to see the relationship between accuracy and latitude and longitude. \[ Accuracy = \beta_{0} + \beta_{1}Latitude + \beta_{2}Longitude + \beta_{3}Latitude\times Longitude + \epsilon \]

reg <- biglm(Accuracy~Lattitude+Longitude+Lattitude*Longitude,data=x)
reg %>% coeftest %>% as.table %>% kable
Estimate Std. Error z value Pr(>|z|)
(Intercept) 93.4328276 1.3290097 70.302595 0
Lattitude -0.3636014 0.0244292 -14.883893 0
Longitude -0.3164779 0.0179775 -17.604094 0
Lattitude:Longitude 0.0033318 0.0003352 9.940549 0

In this linear regression we use biglm() instead of lm() because we have billions of data points, the regular lm() function will generate a huge object up to 9 Gigabytes and eat up all the memory. However biglm() will overcome this problem by gradually update the coefficient matrix by calculate the data row by row.

And the coefficient of the regression shows it is the same as we visualized. As latitude or longitude increases 1 degree, the accuracy will decrease 0.36 and 0.32 respectively, both statistically significant. The interactive term is significant as well, while the magnitude is so small and we can ignore that. We know that the latitude can vary 40 degrees and the longitude can vary 140 degrees across Russia, which can bring substantial difference in the accuracy across broad.

Internet Request Motion in Moscow

In this part, we want to visualize the motion of the people who make mobile internet request in Moscow. We select the User IDs that have been to five famous landmarks in Moscow, who can be seen as tourists in Moscow, and visualize their mobile internet request across hours in one day. Our data only contains hour 13-22, so we can only visualize these ten hours. Notice that there may be hundreds of internet requests, but the number of unique ID is around 20, and is shown on the upper-right panel. The selector of hour and landmark is also in this panel. The description of each data point will be shown after the icon of that point is clicked, which will be User ID and Time Stamp.

This is a screen shot of the interactive map (In shiny app, it is Internet Request in Moscow map tab):

To draw this map and read it clearly, we have to find a map that provide English location names on Russia territory. Unfortunately all the default map providers in leaflet does not have English location names on foreign countries, thus we use Mapbox as our custom map provider to plot this map. We want to see the clusterness of the internet request, so we use marker clusters when drawing individual points on to the map, they will show the number of points in one cluster. When we zoom in, the cluster will spread out and finally showing individual points.

First let us look at the general pattern of internet request of those people who has been into these five landmarks. The numbers of unique ID and the numbers of request peaks at afternoon and hits the bottom at night with no record in hour 22. This might be due to at night tourists go back to their hotel and connect to the hotel WiFi, so they do not need to make internet request via telecom.

The next thing that is worthy noticing is there are two airports in Moscow: Vnukovo International airport on the bottom-left of the map, and the Sheremetyevo International Airport on the upper-left of the map. Almost all the internet requests are during hour 13 to 17. In each of these hours the ID in that airport is not the same, which means this airport is receiving new tourist every hour. There is no record in the evening at the airport, maybe it is due to people who arrive in Moscow at night will not go to the landmarks, probably go straight to their hotels.

Most of the internet records are clustered at the center of Moscow, the area around Kremlin and Red Square etc. This shows that no matter what place people visit in Moscow, the landmarks at the central Moscow are the must-visited places for most of the tourists to Moscow.

Also, we notice that many of the cluster of internet request is on a bridge or at the waterfront, this may be due to the bridge and waterfront are great places for photography, people may take photos there using their mobile phones, and then upload onto the social media, which requires internet request.

Now, we take a look at the airports from where our tourists come. It is a little bit surprised that people visiting St. Basil’s Cathedral all come from Vnukovo International Airport, since Sheremetyevo International Airport handles as twice as many passengers than it. Similar situation happens to tourist who visited GUM Department Store (aka. Glavny Univeralny Magazin), with only 7 records occur in Sheremetyevo International Airport. Another significant finding is that there is no Internet usage record in any airports from people who visit Patriarch’s Pond. It is possible that they are all local citizens who just go to the pond for a walk instead of tourists. After all, it is not a historical architecture you could not find anywhere other than Moscow or a must-go-to in Russia. As for Bolshoi Theatre and Moscow Metro, there is no noticeable difference between the numbers of records in both airports.

6 Conclusion

There may be some limitations in this project. First, the data is the mobile internet request data from one carrier in Mideast and Russia, we do not know whether the user of this carrier can represent all the people in that country, as there might be systematic bias in the sample, say, poor people tend to use cheaper carrier. Maybe we should collect more information about this carrier and the users’ characteristics of the carrier to make a further discussion.

Second, we use the number of request records in our analysis, which might reveal some important information in the data set. In the analysis of population and GDP of Mideast countries, I have mentioned some alternative ways that can use unique IDs to do the analysis. For the internet request motion in Moscow part, we can also use the unique IDs to visualize the motion of people rather than internet request, however, a person may have many requests in many places during one hour, it is hard to determine which point we should choose. Besides, the data is only available when people made internet request, thus it is hard to track a person’s location when he does not make internet request. But these alternatives can be the future directions to try.

Third, there are a few bugs in the shiny apps. When we play the animation interactive map, the background of the map is always flashing because each hour step the shiny generates a new map under the hood. We try to use the JavaScript plugin of leaflet: Leaflet.timeline, but it turns out to have even more bugs than shiny, so we finally choose to use Shiny’s own slider selector. Also, the slider selectors of the two maps is hard to drag, and the hardness is different on different group member’s computer. We think this might be a bug of shiny itself.

As far as the lesson learned, we could have done better in exploring the deep meaning or patterns of the data. Instead, we spent tons of hours trying to debug these bugs in shiny and javascript, or the more beatiful way to visualize our maps using Shiny. It was really time-consuming and have the least marginal benifit, and drifted us from analyzing the data deeper and discovering possible resaons or stories behind these findings.


  1. zw2389@columbia.edu

  2. xc2358@columbia.edu

  3. yw2902@columbia.edu

  4. cp2923@columbia.edu

LS0tDQp0aXRsZTogIkFuYWx5c2lzIG9mIE1vYmlsZSBTaWduYWwgRGF0YSBpbiBNaWRlYXN0IGFuZCBSdXNzaWEiDQphdXRob3I6IEdyb3VwIE1lbWJlcnM6WmhpcnVpIFdhbmdeW3p3MjM4OUBjb2x1bWJpYS5lZHVdLCBYaWthaSBDaGVuXlt4YzIzNThAY29sdW1iaWEuZWR1XSwNCiAgWWFxaW5nIFdhbmdeW3l3MjkwMkBjb2x1bWJpYS5lZHVdLCBDaGFuZyBQYW5eW2NwMjkyM0Bjb2x1bWJpYS5lZHVdDQpkYXRlOiAiTmV3IFlvcmssIGByIFN5cy5EYXRlKClgIg0Kb3V0cHV0Og0KICBodG1sX25vdGVib29rOg0KICAgIHRvYzogeWVzDQotLS0NCg0KIzEgSW50cm9kdWN0aW9uDQojIzEpIFdoeSB0aGlzIHRvcGljDQpXaXRoIHRoZSBkZXZlbG9wbWVudCBvZiBJbnRlcm5ldCBhbmQgc2lnbmFsIHRlY2huaXF1ZXMsIHNtYXJ0cGhvbmUgcGxheXMgYW4gZXNzZW50aWFsIHJvbGUgaW4gcGVvcGxl4oCZcyBsaWZlLiBUZW4geWVhcnMgYWdvLCBwZW9wbGUgb25seSB1c2VkIG1vYmlsZSB0byB0ZXh0IGFuZCBtYWtlIHBob25lIGNhbGxzLCBidXQgbm93YWRheXMgc21hcnRwaG9uZXMgY2FuIGRvIGFsbCBraW5kcyBvZiBzdHVmZiwgc3VjaCBhcyBzdXJmaW5nIHRoZSBpbnRlcm5ldCwgc2VuZGluZyB0aGUgZW1haWxzLCB2aWRlbyBjaGF0dGluZyB3aXRoIGZyaWVuZHMgb3IgZXZlbiBwYXlpbmcgYmlsbHMgZXRjLiBTbywgd2Ugd2FudCB0byBzZWUgaG93IHBvcHVsYXIgbW9iaWxlIGlzIGluIGRpZmZlcmVudCBjb3VudHJpZXMgYW5kIHdoYXQgcGF0dGVybnMgb2YgaW50ZXJuZXQgcmVxdWVzdCBieSBtb2JpbGUgYWNyb3NzIHRpbWUgaW4gb25lIGRheSBhcmUuIEFsc28sIHRoZSBtb2JpbGUgb3BlcmF0b3JzIGNhbiBnZXQgdGhlIGxvY2F0aW9ucyBvZiB0aGUgdXNlcnMgd2hlbiB0aGV5IG1ha2UgcmVxdWVzdHMsIGJ1dCB3aXRoIHNvbWUgc2lnbmFsIHVuY2VydGFpbnR5LCBpdCBpcyBhbHNvIHdvcnRoeSB0byBzdHVkeSB0aGUgZ2VvLWxvY2F0aW9uIGluZm9ybWF0aW9uIGFuZCBzZWUgdGhlIHNwYXRpYWwgcGF0dGVybnMgb2Ygc2lnbmFsIGFjY3VyYWN5Lg0KDQpJbiB0aGlzIHByb2plY3QsIHdlIHdpbGwgZm9jdXMgb24gc29tZSBzcGVjaWZpYyBhcmVhcyBpbiB0aGUgd29ybGQuIFRoZSBtaWRkbGUgZWFzdCBjb3VudHJpZXMgYXJlIGFsbCBjbG9zZSB0byBlYWNoIG90aGVyIHdoaWxlIHRoZXkgaGF2ZSB2ZXJ5IGRpZmZlcmVudCBuYXRpb25hbCBjb25kaXRpb25zLiBSdXNzaWEgaGFzIHZhc3QgdGVycml0b3J5IHNvIHRoZSBtb2JpbGUgc2lnbmFsIG1heSB2YXJ5IGFjcm9zcyB0aGUgY291bnRyeS4gVGhlIHN0dWR5IG9mIHRoZXNlIHR3byBhcmVhcyBtYXkgcHJvZHVjZSB2ZXJ5IGludGVyZXN0aW5nIHJlc3VsdHMgc28gd2UgdXNlZCBtb2JpbGUgcmVxdWVzdCBkYXRhIGZyb20gdGhlc2UgY291bnRyaWVzIHRvIGV4YW0gdGhlIHVzZSBvZiBtb2JpbGUgYW5kIHNpZ25hbCBnZW8tbG9jYXRpb24gaW5mb3JtYXRpb24gaW4gTWlkZGxlIEVhc3QgYW5kIFJ1c3NpYW4uDQoNCldlIHVzZWQgdGhlIGRhdGEgdmlzdWFsaXphdGlvbiBhbmQgc3RhdGlzdGljYWwgbWV0aG9kIHRvIHVuZGVyc3RhbmQgbW9iaWxlIHBvcHVsYXJpdHkgYW5kIHNpZ25hbCBhY2N1cmFjeSBpbiBkaWZmZXJlbnQgY291bnRyaWVzLCBmb3VuZCB0aGUgdW5kZXJseWluZyByZWFzb24gb2YgZGlmZmVyZW50IHBvcHVsYXJpdHkgYW5kIGFjY3VyYWN5LiBJbiBhZGRpdGlvbiwgd2UgYWxzbyBkZXZlbG9wZWQgYSBtb2JpbGUgc2lnbmFsIHRyYWNraW5nIHNpdGUgY2FsbGVkIE1vYmlsZSBTaWduYWwuIEl0IGxpc3RzIG1vYmlsZSB1c2FnZSByZWNvcmRzIGFjcm9zcyB0aW1lIGZvciB0aHJlZSBkYXlzIGluIGEgcm93IGJvdGggaW4gTWlkZGxlIEVhc3QgYW5kIFJ1c3NpYSBhcyB3ZWxsIGFzIHRvb2xzIGFuZCBpbmZvcm1hdGlvbiBuZWVkZWQgdG8gYmUgYWJsZSB0byBoYXZlIGEgY29tcHJlaGVuc2l2ZSB1bmRlcnN0YW5kaW5nIG9mIHRoZSB2YXJpYXRpb25zIGFjcm9zcyBjb3VudHJpZXMgb3IgYXJlYXMgcmVzcGVjdGl2ZWx5Lg0KDQoNCiMjMikgUmVzZWFyY2ggUXVlc3Rpb25zDQpGcm9tIHRoZSBkYXRhLCB3ZSB0cnkgdG8gZmlndXJlIG91dCBmb3VyIHF1ZXN0aW9ucyBpbiBwb3B1bGFyaXR5IG9mIG1vYmlsZTogIA0KYS4gTnVtYmVyIG9mIG1vYmlsZSB1c2VycyBpbiBkaWZmZXJlbnQgY291bnRyaWVzICANCmIuIFByZXZhbGVuY2Ugb2YgbW9iaWxlIGludGVybmV0IHVzYWdlIGluIGRpZmZlcmVudCBjb3VudHJpZXMgIA0KYy4gRGV2ZWxvcG1lbnQgb2YgbW9iaWxlIGluZHVzdHJ5IGluIGRpZmZlcmVudCBjb3VudHJpZXMgIA0KZC4gVXNhZ2Ugdm9sdW1lIG9mIG1vYmlsZSBhY3Jvc3MgdGltZSBpbiBvbmUgZGF5ICANCg0KQWxzbyB3aXRoIHRoaXMgZGF0YSwgd2UgY2FuIHN0dWR5IG1vcmUgaW50ZXJlc3RpbmcgdG9waWNzIHVzaW5nIGdlby1sb2NhdGlvbiBpbmZvcm1hdGlvbjogIA0KYS4gUGF0dGVybiBvZiBzaWduYWwgYWNjdXJhY3kgaW4gZGlmZmVyZW50IE1pZGVhc3QgY291bnRyaWVzIGFjcm9zcyB0aW1lICANCmIuIFRoZSBtb3ZlbWVudCBwYXR0ZXJuIG9mIG1vYmlsZSBpbnRlcm5ldCByZXF1ZXN0IG9mIHNvbWUgc3BlY2lmaWMgZ3JvdXBzIG9mIHBlb3BsZSAgDQoNCiMjMykgSG93IHRvIGZpbmQgdGhlIGRhdGENClRoZSBkYXRhIHdhcyBmcm9tIFpoaXJ1aSBXYW5n4oCZcyBpbnRlcm4gY29tcGFueS4gSXQgY29udGFpbnMgZGF0YSBvZiB0aHJlZSBkYXlzIGluIDIwMTYgZnJvbSBtaWRkbGUgZWFzdCBjb3VudHJpZXMgYW5kIFJ1c3NpYS4gVGhlIG9yaWdpbmFsIGRhdGEgaXMgMTcuNkcuIFdlIHVwbG9hZCB0aGVtIHRvIFtHb29nbGUgRHJpdmVdKGh0dHBzOi8vZHJpdmUuZ29vZ2xlLmNvbS9vcGVuP2lkPTBCeGh6YTc5OHpMVllVMGRFVFY5d1lUTlZiVFEpLiAgV2UgYWxzbyB1c2VkIGRhdGEgZnJvbSBbV29ybGQgUG9wdWxhdGlvbl0oaHR0cDovL3d3dy53b3JsZG9tZXRlcnMuaW5mby93b3JsZC1wb3B1bGF0aW9uL3BvcHVsYXRpb24tYnktY291bnRyeS8pIGFuZCBHRFAgZGF0YSBmcm9tIFtXb3JsZCBCYW5rXShodHRwOi8vYXBpLndvcmxkYmFuay5vcmcvdjIvZW4vaW5kaWNhdG9yL05ZLkdEUC5NS1RQLkNEP2Rvd25sb2FkZm9ybWF0PWNzdikuDQoNCiMyIFRlYW0gbWVtYmVycyBhbmQgZGlzdHJpYnV0ZWQgY29udHJpYnV0aW9ucw0KV2UgaGF2ZSBmb3VyIGdyb3VwIG1lbWJlcnM6IFpoaXJ1aSBXYW5nICh6dzIzODkpLCBYaWthaSBDaGVuICh4YzIzNTgpLCBZYXFpbmcgV2FuZyAoeXcyOTAyKSBhbmQgQ2hhbmcgUGFuIChjcDI5MjMpLiBUbyBzdGFydCwgWmhpcnVpIGRpZCBhbGwgZGF0YSBjbGVhbmluZywgYW5kIHBsb3R0ZWQgYmFyY2hhcnRzIHRvIHZpc3VhbGl6ZSB0aGUgbnVtYmVyIG9mIHJlY29yZHMgYW5kIGFjY3VyYWN5LiBZYXFpbmcgdGhlbiBkaWQgYW5hbHlzaXMgb24gdGhlIGJhcmNoYXJ0cyBpbiBvcmRlciB0byBnZXQgYSBiYXNpYyBpZGVhIG9mIHRoZSBkYXRhc2V0LiBGdXJ0aGVyLCBaaGlydWkgbWFkZSBzcGF0aWFsIHZpc3VhbGl6YXRpb25zIG9mIGVnby1sb2NhdGlvbiBkYXRhIGluIFIgdG8gZ2VuZXJhdGUgdHdvIG1hcHM6IHRoZSBudW1iZXIgb2YgcmVjb3JkcyBpbiBNaWRkbGUgRWFzdCBhbmQgUnVzc2lhLiBBZnRlciB0aGUgYmFzaWMgc3RlcHMsIFhpa2FpIGNyZWF0ZWQgYSBzaGlueSBBcHAgYW5kIGVtYmVkZGVkIFpoaXJ1aeKAmXMgcGxvdHMgYW5kIG1hcHMgaW4gdGhlIGFwcC4gSGUgYW5kIENoYW5nIGFsc28gbWFuYWdlZCB0byB1c2UgYW5pbWF0aW9ucyB0byB2aXN1YWxpemUgdGhlIGNoYW5nZXMgb2YgZG90cyBpbiB0aGUgbWFwcyBvdmVyIHRpbWUuIEluIGFkZGl0aW9uLCB0aGV5IG9wdGltaXplZCB0aGUgYXBwIHRvIGVuYWJsZSBmaWx0ZXJzIHRvIGNhcHR1cmUgbW9iaWxlIHVzYWdlcyBpbiBzcGVjaWZpYyBsYW5kbWFya3MgaW4gUnVzc2lhLiBBdCBsYXN0LCBmb3IgdGhlIHJlcG9ydCwgWWFxaW5nIGlzIHJlc3BvbnNpYmxlIGZvciBJbnRyb2R1Y3Rpb24sIFRlYW0gYW5kIE1pZGRsZSBFYXN0IHBhcnQgb2YgTWFpbiBBbmFseXNpcywgWmhpcnVpIGlzIHJlc3BvbnNpYmxlIGZvciBBbmFseXNpcyBvZiBEYXRhIFF1YWxpdHksIFJ1c3NpYSBwYXJ0IG9mIE1haW4gQW5hbHlzaXMsIGFuZCBDaGFuZyBhbmQgWGlrYWkgYXJlIHJlc3BvbnNpYmxlIGZvciBFeGVjdXRpdmUgU3VtbWFyeS4NCg0KIzMgRGF0YSBRdWFsaXR5DQpUaGlzIGlzIGEgZGF0YSBzZXQgb2YgbW9iaWxlIHNpZ25hbCBkYXRhLiBJdCBjb25zaXN0cyBvZiB0d28gcGFydHMsIHRoZSBmaXJzdCBwYXJ0IGlzIGZyb20gMjIgY291bnRyaWVzIGluIHRoZSBNaWRkbGUgRWFzdCBkdXJpbmcgRGVjIDEwLTEzIDIwMTYsIGFuZCB0aGUgc2Vjb25kIHBhcnQgaXMgZnJvbSBSdXNzaWEgZHVyaW5nIERlYyAxMC0xMi4gRmlyc3QgbGV0IHVzIGxvb2sgYXQgdGhlIGRhdGEgcXVhbGl0eSBvZiB0aGUgTWlkZWFzdCBkYXRhOg0KDQpgYGB7ciwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCmxpYnJhcnkodGlkeXZlcnNlKQ0KWDIwMTZfMTJfMTFhIDwtIHJlYWRfZGVsaW0oIkM6L1VzZXJzL3dhbmdfL0Rlc2t0b3AvMjAxNi0xMi0xMWEudHh0IiwiXHQiLCBlc2NhcGVfZG91YmxlID0gRkFMU0UsY29sX25hbWVzID0gRkFMU0UsdHJpbV93cyA9IFRSVUUscHJvZ3Jlc3MgPSBGKSAlPiUgaGVhZA0KWDIwMTZfMTJfMTFhDQpgYGANClRoZSBvcmlnaW5hbCBkYXRhIG9mIE1pZGVhc3QgaGFzIDEuOTMgR2lnYWJ5dGVzLCBpdCBoYXMgbm8gY29sdW1uIG5hbWVzIGFuZCBpcyB0YWIgZGVsaW1pdGVkLiBUaGUgY29sdW1ucyBvZiB0aGUgZGF0YSBhcmU6ICoqVGltZXN0YW1wLCBJUCBBZGRyZXNzLCBVc2VyIElELCBMYXRpdHVkZSwgTG9uZ2l0dWRlLCBBY2N1cmFjeSwgQ291bnRyeSoqLiBUaGUgdGltZSBzdGFtcCBoYXMgcHJlY2lzaW9uIHRvIHRoZSBzZWNvbmQsIHdoaWxlIHdlIHdpbGwgbW9zdGx5IGZvY3VzIG9uIHRoZSBhbmFseXNpcyBvbiB0aGUgaG91ciBiYXNpcyBzbyB3ZSB3aWxsIGNvbnZlcnQgaXQgaW50byBob3VycyBsYXRlci4gVGhlIElQIEFkZHJlc3MgYWN0dWFsbHkgZG9lcyBub3QgZ2l2ZSBtdWNoIGluZm9ybWF0aW9uIHVuZGVyIG91ciBhbmFseXNpcyBwdXJwb3NlLCB3ZSB3aWxsIGRyb3AgdGhpcyB2YXJpYWJsZSB0byBrZWVwIGEgc21hbGxlciBjb25zdW1wdGlvbiBvZiBtZW1vcnkuIFRoZSBVc2VyIElEIGlzIHVuaXF1ZSBmb3IgZXZlcnkgbW9iaWxlIHBob25lLCBpbiB0aGUgYW5hbHlzaXMgb2YgTWlkZWFzdCwgd2UgbWFpbmx5IGZvY3VzIG9uIGNvdW50cnkgbGV2ZWwsIHNvIHRoZSBVc2VyIElEIGlzIGFsc28gbm90IGluZm9ybWF0aXZlLCB3ZSB3aWxsIGRyb3AgdGhpcyBjb2x1bW4gYXMgd2VsbC4gQWxzbywgZHVlIHRvIHRoZSBjb3VudHJ5IGxldmVsIGFuYWx5c2lzLCB0aGUgbG9uZ2l0dWRlIGFuZCBsYXRpdHVkZSBpcyB1c2VsZXNzIGFzIGxvbmcgYXMgd2UgaGF2ZSB0aGUgY291bnRyeSBuYW1lIGNvbHVtbiwgd2Ugd2lsbCBhbHNvIGRyb3AgdGhlIGxvbmdpdHVkZSBhbmQgbGF0aXR1ZGUgaGVyZS4gVGhlIGFjY3VyYWN5IGlzIGEgbWVhc3VyZSBvZiB0aGUg4oCYY29uZmlkZW5jZSBpbnRlcnZhbOKAmSB0aGF0IGhvdyBmYXIgdGhlIHJlY29yZGVkIGxvY2F0aW9uIGluZm9ybWF0aW9uIG1pZ2h0IGRpZmZlciBmcm9tIHRoZSBhY3R1YWwgbG9jYXRpb24uIFdoZW4gd2Ugb3BlbiBHb29nbGUgbWFwLCB0aGVyZSB3aWxsIGJlIGEgc29tZXdoYXQgdHJhbnNwYXJlbnQgc2t5IGJsdWUgY2lyY2xlIGFyb3VuZCBvdXIgbG9jYXRpb24sIGFuZCB0aGUgcmFkaXVzIG9mIHRoYXQgY2lyY2xlIGlzIHRoZSBhY2N1cmFjeSBoZXJlLiBNYXliZSBpdCBpcyBiZXR0ZXIgdG8gY2FsbCBpdCDigJhpbmFjY3VyYWN54oCZIGJlY2F1c2UgdGhlIGxhcmdlciB0aGUgbnVtYmVyLCB0aGUgbGVzcyB0aGUgY29uZmlkZW5jZSB3ZSBoYXZlIGFib3V0IHRoZSBhY3R1YWwgbG9jYXRpb24uIEJ1dCBpbiBteSBjb21wYW55IGNhbGxlZCBpdCDigJhhY2N1cmFjeeKAmSBzbyBsZXQgdXMganVzdCBrZWVwIHRoaXMgd2F5LiBUaGUgZmluYWwgY29sdW1uIGlzIHRoZSBjb3VudHJ5IG9mIHRoZSBtb2JpbGUgcGhvbmUuIEl0IGlzIGFuIElTTyB0d28gbGV0dGVyIGFiYnJldmlhdGlvbiBvZiBlYWNoIGNvdW50cnksIHNvIHdlIGhhdmUgdG8gd2ViLXNjcmFwZSBhIGNvZGUgYm9vayB0byBjb252ZXJ0IHRoZSBhYmJyZXZpYXRpb24gaW50byBhY3R1YWwgY291bnRyeSBuYW1lLiBUaGUgZGF0YSBjbGVhbmluZyBmdW5jdGlvbiBpcyBhcyBmb2xsb3dpbmc6DQpgYGB7cixldmFsPUYsIGV2YWw9RiwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCmxpYnJhcnkocnZlc3QpDQpjb2RlYm9vayA8LSAnaHR0cDovL3d3dy53b3JsZGF0bGFzLmNvbS9hYXRsYXMvY3R5Y29kZXMuaHRtJyAlPiUgDQogIHJlYWRfaHRtbCAlPiUgDQogIGh0bWxfbm9kZXMoJ3RhYmxlJykgJT4lIA0KICAuW1sxXV0gJT4lIA0KICBodG1sX3RhYmxlKCkNCg0KQ2xlYW5EYXRhX01pZGVhc3QgPC0gZnVuY3Rpb24oaW5wdXQsb3V0cHV0KXsNCiAgbGlicmFyeSh0aWR5dmVyc2UpDQogIHggPC0gcmVhZF9kZWxpbShpbnB1dCwNCiAgICAiXHQiLCBlc2NhcGVfZG91YmxlID0gRkFMU0UsIGNvbF9uYW1lcyA9IEZBTFNFLA0KICAgIHRyaW1fd3MgPSBUUlVFKQ0KICBjb2xuYW1lcyh4KSA8LSBjKCdUaW1lc3RhbXAnLCdJUCBBZGRyZXNzJywnVXNlciBJRCcsJ0xhdGl0dWRlJywnTG9uZ2l0dWRlJywnQWNjdXJhY3knLCdDb3VudHJ5JykNCiAgeCRDT1VOVFJZIDwtIGNvZGVib29rJENPVU5UUllbbWF0Y2goeCRDb3VudHJ5LGNvZGVib29rJGBBMiAoSVNPKWApXQ0KICB4IDwtIHggJT4lIHNlbGVjdChUaW1lc3RhbXAsQWNjdXJhY3ksQ09VTlRSWSkNCiAgd3JpdGVfY3N2KHgsb3V0cHV0KQ0KfQ0KQ2xlYW5EYXRhX01pZGVhc3QoIkM6L1VzZXJzL3dhbmdfL0Rlc2t0b3AvMjAxNi0xMi0xMWEudHh0IiwiQzovVXNlcnMvd2FuZ18vRGVza3RvcC8yMDE2LTEyLTExYV9uZXcuY3N2IikNCkNsZWFuRGF0YV9NaWRlYXN0KCJDOi9Vc2Vycy93YW5nXy9EZXNrdG9wLzIwMTYtMTItMTJhLnR4dCIsIkM6L1VzZXJzL3dhbmdfL0Rlc2t0b3AvMjAxNi0xMi0xMmFfbmV3LmNzdiIpDQpDbGVhbkRhdGFfTWlkZWFzdCgiQzovVXNlcnMvd2FuZ18vRGVza3RvcC8yMDE2LTEyLTEzYS50eHQiLCJDOi9Vc2Vycy93YW5nXy9EZXNrdG9wLzIwMTYtMTItMTNhX25ldy5jc3YiKQ0KYGBgDQoNClRoZW4gbGV0IHVzIGxvb2sgYXQgdGhlIGRhdGEgb2YgUnVzc2lhOg0KYGBge3IsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQpYMjAxNl8xMl8xMGIgPC0gcmVhZF9kZWxpbSgiQzovVXNlcnMvd2FuZ18vRGVza3RvcC8yMDE2LTEyLTEwYi50eHQiLCJcdCIsIGVzY2FwZV9kb3VibGUgPSBGQUxTRSxjb2xfbmFtZXMgPSBGQUxTRSwgdHJpbV93cyA9IFRSVUUscHJvZ3Jlc3MgPSBGKSAlPiUgaGVhZA0KWDIwMTZfMTJfMTBiDQpgYGANCg0KVGhlIG9yaWdpbmFsIGRhdGEgb2YgUnVzc2lhIGhhcyAxNS42IEdpZ2FieXRlcywgaXQgaXMgYWxzbyB0YWIgZGVsaW1pdGVkIGFuZCBoYXMgbm8gY29sdW1uIG5hbWVzLiBUaGUgY29sdW1ucyBvZiB0aGUgZGF0YSBhcmUgKipUaW1lIFN0YW1wKiosICoqSVAgQWRkcmVzcyoqLCAqKlVzZXIgSUQqKiwgKipMYXRpdHVkZSoqLCAqKkxvbmdpdHVkZSoqLCAqKkFjY3VyYWN5KiosICoqV2ktRmkgTmV0d29ya3MgTmVhcmJ5KiosICoqR1NNIFRvd2VycyoqLCAqKkNvdW50cnkqKi4gVGhlIFRpbWUgU3RhbXAsIElQIGFkZHJlc3MgYW5kIEFjY3VyYWN5IGFyZSB0aGUgc2FtZSBhcyB0aGUgZGF0YSBvZiBNaWRlYXN0LCB3ZSB3aWxsIHJlbWFpbiB0aGUgc2FtZSBwcm9jZXNzaW5nIG1ldGhvZCBhcyBpbiB0aGUgTWlkZWFzdCBwYXJ0LiBJbiB0aGlzIHBhcnQgb2YgYW5hbHlzaXMsIHdlIHdpbGwgZm9jdXMgb24gaW5kaXZpZHVhbCBsZXZlbCwgc28gdGhlIFVzZXIgSUQsIExhdGl0dWRlIGFuZCBMb25naXR1ZGUgaW5mb3JtYXRpb24gaXMgdmVyeSBjcnVjaWFsLCB3ZSB3aWxsIG5vdCBkcm9wIHRoZW0gYXMgaW4gdGhlIHByZXZpb3VzIHBhcnQuIFRoZSBXaS1GaSBOZXR3b3JrcyBOZWFyYnksIEdTTSBUb3dlcnMgYW5kIENvdW50cnkgZG9lcyBub3QgcHJvdmlkZSB1c2VmdWwgaW5mb3JtYXRpb24gZm9yIHVzIHRvIGFuYWx5emUsIHdlIHdpbGwgZHJvcCB0aGVtLiBUaHVzLCB0aGUgY29kZSBmb3IgY2xlYW5pbmcgdGhlIGRhdGEgaXMgYXMgZm9sbG93Og0KYGBge3IsZXZhbD1GfQ0KQ2xlYW5EYXRhX1J1c3NpYSA8LSBmdW5jdGlvbihpbnB1dCxvdXRwdXQpew0KICBsaWJyYXJ5KHRpZHl2ZXJzZSkNCiAgeCA8LSByZWFkX2RlbGltKGlucHV0LA0KICAgICAgICAgICAgICAgICAgIlx0IiwgZXNjYXBlX2RvdWJsZSA9IEZBTFNFLCBjb2xfbmFtZXMgPSBGQUxTRSwNCiAgICAgICAgICAgICAgICAgIHRyaW1fd3MgPSBUUlVFKQ0KICBjb2xuYW1lcyh4KSA8LSBjKCdUaW1lIFN0YW1wJywnSVAgQWRkcmVzcycsJ1VzZXIgSUQnLCdMYXRpdHVkZScsJ0xvbmdpdHVkZScsJ0FjY3VyYWN5JywnV2lmaSBOZXR3b3JrcyBOZWFyYnknLCdHU00gVG93ZXJzJywnQ291bnRyeScpDQogIHggPC0geCAlPiUgc2VsZWN0KGBUaW1lIFN0YW1wYCxgVXNlciBJRGAsYExhdGl0dWRlYCxgTG9uZ2l0dWRlYCxgQWNjdXJhY3lgKQ0KICB3cml0ZV9jc3YoeCxvdXRwdXQpDQp9DQpDbGVhbkRhdGFfUnVzc2lhKCJDOi9Vc2Vycy93YW5nXy9EZXNrdG9wLzIwMTYtMTItMTBiLnR4dCIsIkM6L1VzZXJzL3dhbmdfL0Rlc2t0b3AvMjAxNi0xMi0xMGJfbmV3LmNzdiIpDQpDbGVhbkRhdGFfUnVzc2lhKCJDOi9Vc2Vycy93YW5nXy9EZXNrdG9wLzIwMTYtMTItMTFiLnR4dCIsIkM6L1VzZXJzL3dhbmdfL0Rlc2t0b3AvMjAxNi0xMi0xMWJfbmV3LmNzdiIpDQpDbGVhbkRhdGFfUnVzc2lhKCJDOi9Vc2Vycy93YW5nXy9EZXNrdG9wLzIwMTYtMTItMTJiLnR4dCIsIkM6L1VzZXJzL3dhbmdfL0Rlc2t0b3AvMjAxNi0xMi0xMmJfbmV3LmNzdiIpDQpgYGANCg0KVGhlIGRhdGEgaXMgdGhlIHJlY29yZHMgZnJvbSB0ZWxlY29tIGNvbXBhbnksIHRoZXkgYnkgbmF0dXJlIGhhdmUgbm8gbWlzc2luZyB2YWx1ZSBvciBvdXRsaWVycy4gSG93ZXZlciwgdGhlcmUgYXJlIHJlY29yZHMgdGhhdCBkbyBub3QgYmVsb25nIHRvIG9uZSBkYXkgYXBwZWFyIGluIHRoZSBkYXRhIG9mIHRoYXQgZGF5LiBJbiB0aGUgYW5hbHlzaXMgcHJvY2Vzcywgd2Ugd2lsbCBkbyB0aGUgZGF0YSBjbGVhbmluZyBwcm9jZXNzIHRvIGRyb3AgYWxsIHRoZXNlIHJvd3MuDQoNCldlIGhhdmUgaW50ZWdyYXRlZCB0aGUgZmlyc3QgMTAwMCByb3dzIG9mIGRhdGEgZnJvbSBlYWNoIGRheSBpbiBNaWRlYXN0IGFuZCBSdXNzaWEgaW50byBvdXIgW3NoaW55IGFwcF0oaHR0cHM6Ly96aGlydWkuc2hpbnlhcHBzLmlvL21vYmlsZV9zaWduYWwvKSB1bmRlciB0aGUgKipkYXRhKiogdGFiLiBUaGUgY29kZSBvZiB0aGUgc2hpbnkgYXBwIGlzIG9uIHRoZSBbR2l0aHViXShodHRwczovL2dpdGh1Yi5jb20vemhpcnVpd2FuZy9Nb2JpbGUtU2lnbmFsLVF1ZXN0KS4NCg0KIzQgRXhlY3V0aXZlIFN1bW1hcnkNCk1vYmlsZSB1c2FnZSBpcyBhbiBhcHBlYWxpbmcgdG9waWMuIE9uIHRoZSBtaWNybyBhc3BlY3QsIHN0dWR5aW5nIG9uZeKAmXMgaW50ZXJuZXQgcmVxdWVzdCByZWNvcmRzIGNhbiBoZWxwIHVzIGtub3cgYWJvdXQgb25l4oCZcyBsaXZpbmcgY2lyY2xlLCBsaWZlc3R5bGUgYW5kIGV0YywuIG9uIHRoZSBtYWNybyBhc3BlY3QsIGFuYWx5emluZyBwZW9wbGXigJlzIG1vYmlsZSByZXF1ZXN0IGRhdGEgYXMgd2VsbCBhcyBtb2JpbGUgc2lnbmFsIGFjY3VyYWN5IHJldmVhbHMgYSBsb3QgYWJvdXQgdGhlIGNvdW50cnnigJlzIGRldmVsb3BtZW50LCBsZXZlbCBvZiB3ZWFsdGgsIG9yIGV2ZW4gdGhlIGNvdW50cmllc+KAmSBpbmZyYXN0cnVjdHVyZSBkZXZlbG9wbWVudC4NCg0KSW4gdGhpcyBwcm9qZWN0LCB3ZSBmb2N1cyBvbiBzb21lIHNwZWNpZmljIGFyZWFzIGluIHRoZSB3b3JsZC4gVGhlIG1pZGRsZSBlYXN0IGNvdW50cmllcyBhcmUgYWxsIGNsb3NlIHRvIGVhY2ggb3RoZXIgd2hpbGUgdGhleSBoYXZlIHZlcnkgZGlmZmVyZW50IG5hdGlvbmFsIGNvbmRpdGlvbnMuIFJ1c3NpYSBoYXMgdmFzdCB0ZXJyaXRvcnkgc28gdGhlIG1vYmlsZSBzaWduYWwgbWF5IHZhcnkgYWNyb3NzIHRoZSBjb3VudHJ5LiBUaGUgc3R1ZHkgb2YgdGhlc2UgdHdvIGFyZWFzIG9idGFpbnMgc29tZSBpbnRlcmVzdGluZyByZXN1bHRzLCBhbmQgd2UgYXJlIGdvaW5nIHRvIHByZXNlbnQgc29tZSByZXZlYWxpbmcgZmluZGluZ3MgaW4gdGhpcyBzaG9ydCBzdW1tYXJ5Lg0KDQpGaXJzdCwgd2UgdG9vayBhIGxvb2sgYXQgTWlkZGxlIEVhc3QgY291bnRyaWVzLiBIZXJlIGlzIHNpbXBseSBhIHBsb3Qgc2hvd2luZyB0aGUgbnVtYmVyIG9mIG1vYmlsZSB1c2FnZSByZWNvcmRzIGluIGRpZmZlcmVudCBjb3VudHJpZXMuDQoNCiFbXSguL0dJRi9zdW1tYXJ5MS5qcGVnKQ0KDQpGcm9tIHRoZSBwbG90IGFib3ZlIHdlIGNhbiBzZWUgdGhhdCBUdXJrZXksIFNhdWRpIEFyYWJpYSBhbmQgVW5pdGVkIEFyYWIgRW1pcmF0ZXMgaGF2ZSB0aGUgaGlnaGVzdCBudW1iZXIgb2YgcmVjb3JkcywgYXBwcm9hY2hpbmcgMS41IG1pbGxpb24uIEFsbCBvZiB0aGVzZSB0aHJlZSBjb3VudHJpZXMgcmFuayB0aGUgdG9wIGluIHRoZSBNaWRkbGUgRWFzdCBUb3RhbCBHRFAgUmFua2luZyBsaXN0LCBzbyBpdCBtYWtlcyBzZW5zZSB0aGF0IHRoZXNlIGNvdW50cmllcyBoYXZlIHRoZSBsYXJnZXN0IG51bWJlcnMgb2YgYWN0aXZlIG1vYmlsZSB1c2Vycy4gSW4gZ2VuZXJhbCwgdGhlIHNtYWxsZXIgb3IgdGhlIHBvb3JlciBjb3VudHJpZXMgdGVuZCB0byBoYXZlIGZld2VyIHJlY29yZHMuIEhvd2V2ZXIsIHRoZSBudW1iZXIgb2YgcmVjb3JkcyBpbiBzbWFsbCBjb3VudHJpZXMgbGlrZSBDeXBydXMgaXMgbW9yZSB0aGFuIGZvdXIgdGltZXMgb2YgdGhhdCBpbiBsYXJnZSBjb3VudHJpZXMgbGlrZSBJcmFuLCB3aGljaCBpcyB0b3RhbGx5IHVuZXhwZWN0ZWQuDQoNCkhvd2V2ZXIsIGdpdmVuIHRoZSB1bmlxdWVuZXNzIG9mIEN5cHJ1cywgaXQgbWFrZSBzZW5zZS4gQXMgYSBzbWFsbCBpc2xhbmQgY291bnRyeSB3aXRoIGdyZWF0IHRvdXJpc20gcmVzb3VyY2VzLCBDeXBydXMgaGFzIHRvdXJpc3RzIGZyb20gbmVhcmJ5IGNvdW50cmllcyBhbGwgeWVhciBhcm91bmQuIFBlb3BsZSBsb3ZlIHRvIGdvIHRoZXJlIGZvciBsaXR0bGUgYnJlYWtzLiBFc3BlY2lhbGx5IGZvciBFdXJvcGVhbnMsIEN5cHJ1cyBpcyBqdXN0IGEgc2hvcnQtZmxpZ2h0IGF3YXksIGFuZCBoYXMgbXVjaCBsb3dlciBsaXZpbmcgZXhwZW5zZSB0aGFuIG1vc3QgRXVyb3BlYW4gY291bnRyaWVzIGFuZCBvdGhlciBNaWRlYXN0IHRvdXJpc20gY291bnRyaWVzIGxpa2UgVW5pdGVkIEFyYWIgRW1pcmF0ZXMuIFRoZXJlZm9yZSBpdCBpcyBoaWdobHkgcG9zc2libGUgdGhhdCBhIGxhcmdlIHBvcnRpb24gb2YgdGhlIG51bWJlciBvZiByZWNvcmRzIGNvbWVzIGZyb20gZm9yZWlnbiB0b3VyaXN0cy4NCg0KSW4gYWRkaXRpb24sIHNpbmNlIEN5cHJ1cyBpcyBhIHNtYWxsIGlzbGFuZCBjb3VudHJ5IHdoaWNoIGRvIG5vdCBoYXZlIG11Y2ggcG90ZW50aWFsIGZvciBhZ3JpY3VsdHVyZSBvciBpbmR1c3RyeSwgaXQgaXMgcmVhc29uYWJsZSB0byBzdWdnZXN0IHRoYXQgbW9iaWxlIGluZHVzdHJ5IGhhcyBhIGhpZ2hlciByZWxhdGl2ZSBkZXZlbG9wbWVudCBpbiBDeXBydXMgdGhhbiBpbiBvdGhlciBNaWRkbGUgRWFzdCBjb3VudHJpZXMsIHdoaWNoIGlzIGNvbnNpc3RlbnQgd2l0aCB0aGUgZWFybGllciByZWFzb25pbmcgdGhhdCBDeXBydXMgaGF2ZSBwcm9zcGVyb3VzIHRvdXJpc20uIEhvd2V2ZXIsIHRoZXJlIGFyZSBzdGlsbCBvdGhlciBwb3NzaWJsZSBleHBsYW5hdGlvbnMgZm9yIHRoaXMgcGF0dGVybi4gRm9yIGV4YW1wbGUsIHRoZSBkYXRhIGl0c2VsZiBtaWdodCBjb21lIGZyb20gYSBzaW5nbGUgY2Fycmllciwgd2hpY2ggY291bGQgYmUgYmFzZWQgaW4gQ3lwcnVzLiBUaGVuLCB0aGUgaHVnZSB2b2x1bWUgb2YgcmVjb3JkcyBpbiBDeXBydXMgd291bGQgbWFrZSBtb3JlIHNlbnNlLCBzaW5jZSBpbiBvdGhlciBjb3VudHJpZXMsIHBlb3BsZSBtYXkgdXNlIG90aGVyIG1ham9yIGNhcnJpZXJzIGFuZCBzdWNoIGdyZWF0IG51bWJlciBvZiByZWNvcmRzIGlzIGludmlzaWJsZSBpbiB0aGlzIGRhdGFzZXQuDQoNCkJlc2lkZXMgdGhlIG51bWJlciBvZiByZWNvcmRzLCB0aGUgb3RoZXIgaW50ZXJlc3RpbmcgZmVhdHVyZSBpbiB0aGlzIGRhdGEgc2V0IGlzIHRoZSBhY2N1cmFjeS4gSXQgaXMgYSBtZWFzdXJlIG9mIHRoZSDigJhjb25maWRlbmNlIGludGVydmFs4oCZIHRoYXQgdGhlIHJlY29yZGVkIGxvY2F0aW9uIGluZm9ybWF0aW9uIGRpZmZlcnMgZnJvbSB0aGUgYWN0dWFsIG9uZS4gU28gYWN0dWFsbHkgdGhlIGxhcmdlciB0aGUgdmFsdWUgaXMsIHRoZSBsZXNzIGNvbmZpZGVuY2Ugd2UgaGF2ZSBhYm91dCB0aGUgbG9jYXRpb24uDQoNCiFbXSguL0dJRi9zdW1tYXJ5Mi5qcGVnKQ0KDQpGcm9tIHRoZSBwbG90IGFib3ZlLCB0aGVyZSBhcmUgZm91ciBjb3VudHJpZXMgaGF2ZSBtZWFuIGFjY3VyYWN5IG92ZXIgMjAwMCBtZXRlcnM6IExpYnlhLCBJcmFxLCBTb3V0aCBTdWRhbiBhbmQgRGVtb2NyYXRpYyBSZXB1YmxpYyBvZiBDb25nby4gQWxsIG9mIHRoZW0gYXJlIGluIHVwaGVhdmFsIG9yIGV4cGVyaWVuY2VkIGh1Z2UgdHVyYnVsZW5jZS4gQnkgc2VhcmNoIG9uIHRoZSBpbnRlcm5ldCwgd2Ugbm90aWNlIHRoYXQgdGhlIHNtb2tlIGZyb20gdGhlIHdhcnMgYWxzbyBhZmZlY3QgdGhlIG1vYmlsZSBzaWduYWwsIGhlbmNlLCBhZmZlY3QgdGhlIGFjY3VyYWN5LiBBZGRpdGlvbmFsbHksIGluIHVuc3RhYmxlIGNvdW50cmllcyBsaWtlIHRoZXNlLCB0aGUgYmFzZSBzdGF0aW9ucyBhcmUgZWFzaWx5IGdldHRpbmcgZGFtYWdlZCwgYW5kIHRoZXJlIGlzIG5vIGV4dHJhIG1vbmV5LCBwZW9wbGUsIHJlc291cmNlcyBvciBtb3RpdmF0aW9ucyBmb3Igc29tZW9uZSB0byBkZXZlbG9wIHRoZSBtb2JpbGUgaW5kdXN0cnksIGJvdGggbW9iaWxlIHBob25lcyBhbmQgYmFzZSBzdGF0aW9ucy4gU28gdGhleSBhcmUgZXhwZWN0ZWQgdG8gaGF2ZSBoaWdoZXN0IGFjY3VyYWN5Lg0KDQpPbiB0aGUgb3RoZXIgaGFuZCwgQ3lwcnVzIGFnYWluIGJlYXRzIG90aGVyIGNvdW50cmllcyB0byBiZSB0aGUgYmVzdCBpbiB0ZXJtcyBvZiBhY2N1cmFjeSBpbiBNaWRkbGUgRWFzdC4gQmVzaWRlcyBpdHMgc3RhYmxlIHBvbGl0aWNhbCBzaXR1YXRpb24sIHRoZSBtYWpvcml0eSBvZiB0aGUgY291bnRyeSBpcyBwbGFpbiwgd2hpY2ggaXMgYmVuZWZpY2lhbCBmb3IgYmFzZSBzdGF0aW9ucy4gRnVydGhlcm1vcmUsIGFzIGEgcG9wdWxhciB0b3VyaXN0IGRlc3RpbmF0aW9uLCBpdCBoYXMgdGhlIG1vdGl2YXRpb24gdG8gYnVpbGQgYSBiZXR0ZXIgZW52aXJvbm1lbnQuIEZvciBleGFtcGxlLCBoaWdoIHF1YWxpdHkgaW5mcmFzdHJ1Y3R1cmVzLCBmb3IgaW50ZXJuZXQgdXNlcnMgaW4gb3JkZXIgdG8gYXR0cmFjdCBtb3JlIHRvdXJpc3RzLiBJbiB0dXJuLCB0b3VyaXN0IHdobyBwcm9iYWJseSBjb21lIGZyb20gcmljaGVyIGNvdW50cmllcyB3b3VsZCB1c2UgaGlnaC1xdWFsaXR5IGNlbGwgcGhvbmVzLiBBbmQgYWxsIG9mIHRoZXNlIGNvdWxkIGxlYWQgdG8gYmV0dGVyIGFjY3VyYWN5Lg0KDQpOb3csIHdlIG1vdmUgdG8gUnVzc2lhLiBIZXJlLCB3ZSBtYWRlIGEgY2xvc2VyIGxvb2sgYXQgdGhlIG1vdmluZyBwYXR0ZXJuIG9mIHNwZWNpZmljIGdyb3VwcywgYW5kIGZvdW5kIHNvbWUgaW50ZXJlc3RpbmcgcGF0dGVybnMgb2YgdG91cmlzdCBvbiBNb3Njb3cgaW4gdGhlIG1hcC4NCg0KIVtdKC4vR0lGL3N1bW1hcnkzLmpwZykNCg0KVGFrZSB0aGlzIHBsb3QgYXMgYW4gZXhhbXBsZSwgdGhlIGJsdWUgZG90cyByZXByZXNlbnQgdGhlIHBvc2l0aW9ucyBvZiBhIGNlcnRhaW4gcGVyc29uLCB3aGljaCBjbGVhcmx5IHJldmVhbCB0aGUgbW92aW5nIHBhdHRlcm4gb2YgdGhlIHBlcnNvbi4gU2luY2UgdGhleSBhbGwgcGVyZmVjdGx5IGxpbmVkIHVwIHdpdGggZWFjaCBvdGhlciwgaXQgc2VlbXMgdGhhdCB0aGUgcGVyc29uIHdhcyBxdWV1aW5nIGluIHRoZSBsaW5lIGZvciBhIHRyYXZlbGluZyBzaWdodCBvciBtYXliZSBqdXN0IGEgcmVzdGF1cmFudC4gSG93ZXZlciwgc2ltaWxhciBsaW5pbmcgcGF0dGVybnMgd2VyZSBub3QgZXZlcnl3aGVyZSBpbiB0aGUgbWFwIGFzIGl0IHdhcyBzdXBwb3NlZCB0byBiZS4gUGVvcGxlIGRvIG5vdCBsaW5lIHVwIHRvIHB1cmNoYXNlIHRoZSB0aWNrZXRzIG9yIHdhaXQgdG8gZW50ZXIgdGhlIHNpZ2h0cywgc28gaXQgaXMgc2FmZSBmb3IgdXMgdG8gY29uY2x1ZGUgdGhhdCB0aGlzIHBlcmlvZCBtaWdodCBub3QgYmUgZHVyaW5nIGEgYnVzeSB0cmF2ZWxpbmcgc2Vhc29uIGluIE1vc2NvdywgYW5kIHRvdXJpc3QgY291bGQgZ28gd2hlcmV2ZXIgdGhleSB3YW50IHRvIHZpc2l0IHdpdGhvdXQgd2FpdGluZyBhIGxpbmUuDQoNCkFub3RoZXIgZmluZGluZyBpcyB0aGF0IG1hbnkgb2YgdGhlIGNsdXN0ZXIgb2YgaW50ZXJuZXQgcmVxdWVzdCBpcyBvbiBhIGJyaWRnZSBvciBhdCB0aGUgd2F0ZXJmcm9udCwgdGhpcyBtYXkgYmUgZHVlIHRvIHRoZSBmYWN0IHRoYXQgYnJpZGdlcyBhbmQgd2F0ZXJmcm9udCBhcmUgZ3JlYXQgcGxhY2VzIGZvciBwaG90b2dyYXBoeSwgcGVvcGxlIG1heSB0YWtlIHBob3RvcyB0aGVyZSB1c2luZyB0aGVpciBtb2JpbGUgcGhvbmVzLCBhbmQgdGhlbiB1cGxvYWQgb250byB0aGUgc29jaWFsIG1lZGlhLCB3aGljaCByZXF1aXJlcyBpbnRlcm5ldCByZXF1ZXN0Lg0KDQpUbyBzdW0gaXQgdXAsIGluIE1pZGRsZSBFYXN0LCB0aGUgbGFyZ2VyIG9yIHRoZSByaWNoZXIgYSBjb3VudHJ5IGlzLCB0aGUgbW9yZSBtb2JpbGUgdXNhZ2UgcmVjb3JkcyBhbmQgYmV0dGVyIGFjY3VyYWN5IGl0IGhhcywgd2l0aCBvbmUgZXhjZXB0aW9uOiBDeXBydXMuIEFzIGEgZ3JlYXQgdG91cmlzbSBjb3VudHJ5LCBpdCBhdHRyYWN0cyBtYW55IGZvcmVpZ24gdmlzaXRvcnMsIHdobyBtYWtlIGdyZWF0IGNvbnRyaWJ1dGlvbnMgdG8gdGhlIGNvdW50cnnigJlzIG1vYmlsZSB1c2FnZSByZWNvcmRzIGFuZCBpbiB0dXJuIGJyaW5nIGhpZ2gtdGVjaCBzbWFydHBob25lcyB0byBtb3RpdmF0ZSBDeXBydXMgZm9yIGJldHRlciBiYXNlIHN0YXRpb25zLiBBbHNvLCBhcyBleHBlY3RlZCwgY291bnRyaWVzIGluIHVwaGVhdmFsIG9yIGV2ZW4gaW4gd2FyIGhhdmUgZmV3ZXIgcmVjb3JkcyBhbmQgbGFyZ2VyIGFjY3VyYWN5LiBBcyBpbiBSdXNzaWEsIGJhc2VkIG9uIHRoZSBpbnRlcm5ldCByZXF1ZXN0IHNob3dpbmcgaW4gdGhlIG1hcCwgd2UgY2FuIGNvbmNsdWRlIHRoYXQgaXQgaXMgaGlnaGx5IGxpa2VseSBhIG9mZi1zZWFzb24gZm9yIHRvdXJpc20gaW4gTW9zY293LCBhbmQgd2hlbiBwZW9wbGUgdmlzaXQgbmF0dXJhbCBzaWdodHMgc3VjaCBhcyBwb25kLCB0aGV5IHRlbmQgdG8gdXNlIGNlbGwgcGhvbmVzIGZvciBpbnRlcm5ldCBtb3JlIHRoYW4gb2Z0ZW4uDQoNCiM1IE1haW4gQW5hbHlzaXMNCiMjTWlkZGxlIEVhc3QNCmBgYHtyLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KbGlicmFyeShwbG90bHkpDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkoZ2dhbmltYXRlKQ0KbGlicmFyeShsdWJyaWRhdGUpDQpsaWJyYXJ5KGZvcmNhdHMpDQpsaWJyYXJ5KGJpZ2xtKQ0KbGlicmFyeShsbXRlc3QpDQpsaWJyYXJ5KGtuaXRyKQ0KbGlicmFyeShsZWFmbGV0KQ0KWDIwMTZfMTJfMTFhX25ldyA8LSByZWFkX2NzdigiQzovVXNlcnMvd2FuZ18vRGVza3RvcC8yMDE2LTEyLTExYV9uZXcuY3N2Iixwcm9ncmVzcz1GKQ0KWDIwMTZfMTJfMTJhX25ldyA8LSByZWFkX2NzdigiQzovVXNlcnMvd2FuZ18vRGVza3RvcC8yMDE2LTEyLTEyYV9uZXcuY3N2Iixwcm9ncmVzcz1GKQ0KWDIwMTZfMTJfMTNhX25ldyA8LSByZWFkX2NzdigiQzovVXNlcnMvd2FuZ18vRGVza3RvcC8yMDE2LTEyLTEzYV9uZXcuY3N2Iixwcm9ncmVzcz1GKQ0KeCA8LSBiaW5kX3Jvd3MoWDIwMTZfMTJfMTFhX25ldyxYMjAxNl8xMl8xMmFfbmV3LFgyMDE2XzEyXzEzYV9uZXcpDQpgYGANCiMjI051bWJlciBvZiByZWNvcmRzDQpGaXJzdCB3ZSB0b29rIGEgbG9vayBhdCB0aGUgbnVtYmVyIG9mIHJlY29yZHMgaW4gZWFjaCBNaWRkbGUgRWFzdCBjb3VudHJ5LiBGb3IgdGhlIHB1cnBvc2Ugb2YgY29tcGFyaXNvbiwgd2UgaGF2ZSB0d28gb3B0aW9uczogYmFyY2hhcnRzIGFuZCBwaWVjaGFydHMuIEhvd2V2ZXIsIHdpdGggbW9yZSB0aGFuIDIwIGNvdW50cmllcyBpbiB0b3RhbCwgaXQgaXMgZGlmZmljdWx0IHRvIGlkZW50aWZ5IHRoZSBzbGljZSBmb3IgYSBjb3VudHJ5IHdpdGggc21hbGwgcG9ydGlvbiwgb3IgZXZlbiBjb21wYXJlIGl0IHdpdGggYSBzbWFsbGVyIHNsaWNlIHVzaW5nIHBpZWNoYXJ0cywgdGhlcmVmb3JlLCB3ZSBzZXR0bGVkIHdpdGggYmFyY2hhcnRzLg0KYGBge3IsZmlnLndpZHRoPTh9DQp4X2dyb3VwX2NvdW50IDwtIHggJT4lIA0KICBmaWx0ZXIoVGltZXN0YW1wPmFzLkRhdGUoJzIwMTYtMTItMTIgMDA6MDA6MDAgVVRDJykpICU+JSANCiAgZ3JvdXBfYnkoQ09VTlRSWSkgJT4lIA0KICBzdW1tYXJpc2UoY291bnQ9bigpKSAlPiUgDQogIGFycmFuZ2UoY291bnQpDQooeF9ncm91cF9jb3VudCAlPiUgDQogIGdncGxvdChhZXMoeT1jb3VudCx4PWFzX2ZhY3RvcihDT1VOVFJZKSkpKw0KICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIsZmlsbD0nc2t5Ymx1ZTInKSsNCiAgY29vcmRfZmxpcCgpKw0KICB5bGFiKCdOdW1iZXIgb2YgUmVjb3JkcycpKw0KICB4bGFiKCdDb3VudHJ5IE5hbWUnKSsNCiAgZ2d0aXRsZSgnTnVtYmVyIG9mIFJlY29yZHMgYnkgQ291bnRyeScpKSAlPiUgDQogIGdncGxvdGx5DQpgYGANCg0KSW4gb3JkZXIgdG8gZHJhdyB0aGlzIGdyYXBoLCBmaXJzdCB3ZSBmaWx0ZXIgdGhlIGRhdGEgdG8gZHJvcCB0aGUgcm93cyB0aGF0IGRvZXMgbm90IGJlbG9uZyB0byB0aGVzZSB0aHJlZSBkYXlzLiBUaGVuIHdlIGdyb3VwIHRoZSBkYXRhIGJ5IGNvdW50cnkgYW5kIGNvdW50IHRoZSBudW1iZXIgb2YgZWFjaCBjb3VudHJ5LiBXZSB3YW50IHRoZSBiYXIgY2hhcnQgdG8gYmUgc29ydGVkIGJ5IHRoZSBudW1iZXIgb2YgcmVjb3Jkcywgc28gd2UgYXJyYW5nZSB0aGUgY291bnQgdmFyaWFibGUgYW5kIHVzZSBhc19mYWN0b3IoKSBmdW5jdGlvbiB0byByZW1haW4gdGhpcyBvcmRlciB3aGVuIHBhc3NpbmcgdG8gZ2dwbG90LiBXZSBhbHNvIGZsaXAgdGhlIGNvb3JkaW5hdGVzIGZvciBiZXR0ZXIgdmlzdWFsaXphdGlvbiBvZiB0aGUgY291bnRyeSBuYW1lcy4NCg0KRnJvbSB0aGUgcGxvdCBhYm92ZSwgd2UgY2FuIHNlZSB0aGF0IFR1cmtleSwgU2F1ZGkgQXJhYmlhIGFuZCBVbml0ZWQgQXJhYiBFbWlyYXRlcyBoYXZlIHRoZSBoaWdoZXN0IG51bWJlciBvZiByZWNvcmRzLCBhcHByb2FjaGluZyAxLjUgbWlsbGlvbi4gQWxsIG9mIHRoZSB0aHJlZSBjb3VudHJpZXMgcmFuayB0aGUgdG9wIGluIHRoZSBNaWRkbGUgRWFzdCBUb3RhbCBHRFAgUmFua2luZyBsaXN0LCBzbyBpdCBtYWtlcyBzZW5zZSB0aGF0IHRoZXNlIGNvdW50cmllcyBoYXZlIHRoZSBsYXJnZXN0IG51bWJlcnMgb2YgYWN0aXZlIG1vYmlsZSB1c2Vycy4gSW4gZ2VuZXJhbCwgdGhlIHNtYWxsZXIgb3IgdGhlIHBvb3JlciBjb3VudHJpZXMgdGVuZCB0byBoYXZlIGZld2VyIHJlY29yZHMuIEhvd2V2ZXIsIHRoZSBudW1iZXIgb2YgcmVjb3JkcyBpbiBzbWFsbCBjb3VudHJpZXMgbGlrZSBDeXBydXMgaXMgbW9yZSB0aGFuIGZvdXIgdGltZXMgb2YgdGhhdCBpbiBsYXJnZSBjb3VudHJpZXMgbGlrZSBJcmFuLg0KDQpUaGVyZSBhcmUgdHdvIG9idmlvdXMgZmFjdG9ycyBhc3NvY2lhdGVkIHdpdGggdGhlIG51bWJlciBvZiByZWNvcmRzOiBuYXRpb25hbCBwb3B1bGF0aW9uIGFuZCBHRFAsIGFuZCB3ZSBhcmUgZ29pbmcgdG8gZXhwbG9yZSB0aGVtIG9uZSBieSBvbmUuIEhlcmUsIHdlIGZpcnN0IHN0YXJ0IHdpdGggcG9wdWxhdGlvbi4gQnkgZGl2aWRpbmcgdGhlIG51bWJlciBvZiByZWNvcmRzIGJ5IHRoZSBuYXRpb25hbCBwb3B1bGF0aW9uLCB3ZSBvYnRhaW4gdGhlIHByb3BvcnRpb24gb2YgdGhlIGFjdGl2ZSB1c2VycyBpbiB0aGUgbmF0aW9uYWwgcG9wdWxhdGlvbiwgd2hpY2ggY291bGQgYmUgYSBtZWFzdXJlIG9mIGhvdyBwcmV2YWxlbnQgbW9iaWxlIHVzYWdlIGlzIGluIGVhY2ggY291bnRyeS4NCg0KYGBge3IsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsZmlnLndpZHRoPTh9DQpwb3B1bGF0aW9uIDwtICJodHRwOi8vd3d3Lndvcmxkb21ldGVycy5pbmZvL3dvcmxkLXBvcHVsYXRpb24vcG9wdWxhdGlvbi1ieS1jb3VudHJ5LyIgJT4lIA0KICByZWFkX2h0bWwgJT4lIA0KICBodG1sX25vZGVzKCd0YWJsZScpICU+JSANCiAgLltbMV1dICU+JSANCiAgaHRtbF90YWJsZSgpICU+JSANCiAgLlssMjozXQ0KY29sbmFtZXMocG9wdWxhdGlvbilbMl0gPC0gJ1BvcHVsYXRpb24nDQpwb3B1bGF0aW9uJFBvcHVsYXRpb24gPC0gcG9wdWxhdGlvbiRQb3B1bGF0aW9uICU+JSBnc3ViKCcsJywnJywuKSAlPiUgYXMubnVtZXJpYygpDQphIDwtIG1hdGNoKHhfZ3JvdXBfY291bnQkQ09VTlRSWSxwb3B1bGF0aW9uJGBDb3VudHJ5IChvciBkZXBlbmRlbmN5KWApDQphW2EgJT4lIGlzLm5hICU+JSB3aGljaF0gPC0gYygxNiw2MSwxMjEsMTcpDQp4X2dyb3VwX2NvdW50JFBvcHVsYXRpb24gPC0gcG9wdWxhdGlvbiRQb3B1bGF0aW9uW2FdDQooeF9ncm91cF9jb3VudCAlPiUgDQogIG11dGF0ZShwZXJjZW50YWdlPTEwMCpjb3VudC9Qb3B1bGF0aW9uKSAlPiUgDQogIGdncGxvdChhZXMoeT1wZXJjZW50YWdlLHg9YXNfZmFjdG9yKENPVU5UUlkpKSkrDQogIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5IixmaWxsPSdza3libHVlMicpKw0KICBjb29yZF9mbGlwKCkrDQogIHlsYWIoJ051bWJlciBvZiBSZWNvcmRzL1BvcHVsYXRpb24nKSsNCiAgeGxhYignQ291bnRyeSBOYW1lJykrDQogIGdndGl0bGUoJ051bWJlciBvZiBSZWNvcmRzIHRvIFBvcHVsYXRpb24gYnkgQ291bnRyeScpKSAlPiUgDQogIGdncGxvdGx5DQpgYGANCg0KSW4gb3JkZXIgdG8gZHJhdyB0aGlzIGdyYXBoLCB3ZSBmaXJzdCBzY3JhcGUgd29ybGQgcG9wdWxhdGlvbiBpbmZvcm1hdGlvbiBmcm9tIEludGVybmV0LCBhbmQgdGhlbiBtYXRjaCB0aGUgdGFibGUgb250byBvdXIgb3JpZ2luYWwgZGF0YSBhY2NvcmRpbmcgdG8gY291bnRyeSBuYW1lLiBXZSBkaXZpZGUgdGhlIG51bWJlciBvZiByZWNvcmRzIGJ5IHRoZSBwb3B1bGF0aW9uIGFuZCB0aW1lcyAxMDAgdG8gZ2V0IHRoZSBwZXJjZW50YWdlLCB0aGVuIGRyYXcgdGhlIGdyYXBoIHVzZSB0aGUgc2FtZSB0ZWNobmlxdWUgYXMgdGhlIHByZXZpb3VzIHBhcnQuIEFuIGFsdGVybmF0aXZlIG9wdGlvbiBpcyB0byB1c2UgdGhlIG51bWJlciBvZiB1bmlxdWUgSUQgYXMgdGhlIG51bWVyYXRvciB0byBnZXQgdGhlIHBlcmNlbnRhZ2UuIEhvd2V2ZXIsIHdlIHdhbnQgdGhlIG51bWJlciBvZiBpbnRlcm5ldCByZXF1ZXN0IGVhY2ggdXNlciBtYWRlIGNhbiBhbHNvIGJlIGluY2x1ZGVkIGluIHRoaXMgaW5kZXgsIHRodXMgd2UgY2hvb3NlIHRvIHVzZSB0aGUgbnVtYmVyIG9mIHJlY29yZHMgdG8gZ2V0IHRoZSBwZXJjZW50YWdlLg0KDQpXZSBjYW4ga25vdyBmcm9tIHRoZSBwbG90IHRoYXQgVHVya2V5LCBTYXVkaSBBcmFiaWEgYW5kIFVuaXRlZCBBcmFiIEVtaXJhdGVzIGRvIG5vdCByYW5rIHRoZSBoaWdoZXN0IGFueSBtb3JlLCBpbnN0ZWFkIEN5cHJ1cyBoYXMgYW4gZW5vcm1vdXNseSBsYXJnZXIgbnVtYmVyIHRoYW4gb3RoZXIgY291bnRyaWVzOiBuZWFybHkgYSBoYWxmIG9mIHRoZSBjb3VudHJ5IHBvcHVsYXRpb24gaGFzIG1hZGUgaW50ZXJuZXQgcmVxdWVzdCBpbiB0aHJlZSBkYXlzLiBXZSB0aGluayB0aGlzIGlzIGJlY2F1c2UgdGhlIGZhY3QgdGhhdCBDeXBydXMgaXMgYSBzbWFsbCBpc2xhbmQgY291bnRyeSB3aXRoIGdyZWF0IHRvdXJpc20gcmVzb3VyY2VzLiBQZW9wbGUgZnJvbSBuZWFyYnkgY291bnRyaWVzIGxvdmUgdG8gZ28gdGhlcmUgZm9yIGEgbGl0dGxlIGJyZWFrLCBlc3BlY2lhbGx5IEV1cm9wZWFucy4gU28gaXQgaXMgaGlnaGx5IHBvc3NpYmxlIHRoYXQgdGhlIGxhcmdlIG51bWJlciBvZiByZWNvcmRzIGNvbnNpc3Qgb2YgZ3JlYXQgbWFueSBvZiBmb3JlaWduIHRvdXJpc3RzLiBPdGhlciB0aGFuIEN5cHJ1cywgaXQgc2VlbXMgdGhhdCByaWNoZXIgY291bnRyaWVzIGdlbmVyYWxseSBoYXZlIG1vcmUgcmVjb3JkcyBwZXIgcGVyc29uIHRoYW4gcG9vcmVyIG9uZXMuDQoNClRvIGNvbmZpcm0gdGhpcyBmaW5kaW5nLCB3ZSBjaG9vc2UgdG8gZXhhbWluZSB0aGUgcmF0aW8gb2YgbnVtYmVyIG9mIGFjdGl2ZSB1c2VycyB0byB0aGUgdG90YWwgR0RQLCB3aGljaCBjYW4gYmUgYSBtZWFzdXJlIG9mIHRoZSByZWxhdGl2ZSBkZXZlbG9wbWVudCBvZiBtb2JpbGUgaW5kdXN0cnkgdG8gdGhlIHdob2xlIGluZHVzdHJ5IGluIGVhY2ggY291bnRyeS4gV2UgZmluZCB0aGUgdG90YWwgR0RQIGRhdGEgZnJvbSB3b3JsZCBiYW5rIGRhdGEgc2V0LCBhbmQgZGl2aWRlIHRoZSBudW1iZXIgb2YgcmVjb3JkcyB0byB0b3RhbCBHRFAuDQoNCmBgYHtyLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KdXJsIDwtICdodHRwOi8vYXBpLndvcmxkYmFuay5vcmcvdjIvZW4vaW5kaWNhdG9yL05ZLkdEUC5NS1RQLkNEP2Rvd25sb2FkZm9ybWF0PWNzdicNCnRlbXAgPC0gdGVtcGZpbGUoKQ0KZG93bmxvYWQuZmlsZSh1cmwsIHRlbXAsIG1vZGU9IndiIikNCnVuemlwKHRlbXAsICJBUElfTlkuR0RQLk1LVFAuQ0RfRFMyX2VuX2Nzdl92Mi5jc3YiKQ0KdG90YWxnZHAgPC0gcmVhZF9jc3YoIkFQSV9OWS5HRFAuTUtUUC5DRF9EUzJfZW5fY3N2X3YyLmNzdiIsc2tpcCA9IDQpWyxjKDEsMiw2MCldDQp1bmxpbmsodGVtcCkNCmBgYA0KDQpgYGB7ciwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSxmaWcud2lkdGg9OH0NCnRvdGFsZ2RwJENvdW50cnkgPC0gY29kZWJvb2skQ09VTlRSWVttYXRjaCh0b3RhbGdkcCRgQ291bnRyeSBDb2RlYCxjb2RlYm9vayRgQTMgKFVOKWApXQ0KYSA8LSBtYXRjaCh4X2dyb3VwX2NvdW50JENPVU5UUlksdG90YWxnZHAkQ291bnRyeSkNCnhfZ3JvdXBfY291bnQkZ2RwIDwtIHRvdGFsZ2RwJGAyMDE1YFthXQ0KKHhfZ3JvdXBfY291bnQgJT4lIA0KICBtdXRhdGUocGVyY2VudGFnZT1jb3VudC9nZHApICU+JSANCiAgZ2dwbG90KGFlcyh5PXBlcmNlbnRhZ2UseD1hc19mYWN0b3IoQ09VTlRSWSkpKSsNCiAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiLGZpbGw9J3NreWJsdWUyJykrDQogIGNvb3JkX2ZsaXAoKSsNCiAgeWxhYignTnVtYmVyIG9mIFJlY29yZHMvVG90YWwgR0RQJykrDQogIHhsYWIoJ0NvdW50cnkgTmFtZScpKw0KICBnZ3RpdGxlKCdOdW1iZXIgb2YgUmVjb3JkcyB0byBUb3RhbCBHRFAgYnkgQ291bnRyeScpKSAlPiUgDQogIGdncGxvdGx5DQpgYGANCg0KSW4gb3JkZXIgdG8gZHJhdyB0aGlzIGdyYXBoLCB3ZSBmaXJzdCBhdXRvbWF0aWNhbGx5IGRvd25sb2FkIHRoZSBHRFAgZGF0YSBmcm9tIFdvcmxkIEJhbmsgT3BlbiBEYXRhLCB1c2UgdGhlIHNhbWUgd2F5IGFzIGFib3ZlIHRvIG1hdGNoIGl0IHRvIHRoZSBvcmlnaW5hbCBkYXRhLCBhbmQgdGhlbiBkaXZpZGUgdGhlIG51bWJlciBvZiByZWNvcmRzIGJ5IHRvdGFsIEdEUC4gQW4gYWx0ZXJuYXRpdmUgb3B0aW9uIGhlcmUgaXMgdG8gdXNlIEdEUCBwZXIgY2FwaXRhLCBhbmQgdGhlbiB3ZSB3aWxsIGdldCBhIG1lYXN1cmUgb2YgYW4gRW5nZWwtY29lZmZpY2llbnQtbGlrZSBpbmRleCBvZiB0aGUgbW9iaWxlIHBob25lIHVzYWdlLiBIb3dldmVyIGhlcmUgd2Ugd2FudCB0byBmb2N1cyBvbiB0aGUgY291bnRyeSBsZXZlbCBhbmFseXNpcywgc28gd2UganVzdCBnbyB3aXRoIHRoZSByZWxhdGl2ZSBkZXZlbG9wbWVudCBvZiBtb2JpbGUgaW5kdXN0cnkuDQoNCldlIGNhbiBzZWUgdGhhdCBhZ2FpbiBDeXBydXMgc3VycGFzc2VzIHRoZSBvdGhlciBjb3VudHJpZXMgYnkgYSBodWdlIGFtb3VudC4gU2luY2UgaXQgaXMgYSBzbWFsbCBpc2xhbmQgY291bnRyeSB3aGljaCBkbyBub3QgaGF2ZSBtdWNoIHBvdGVudGlhbCBmb3IgYWdyaWN1bHR1cmUgb3IgaW5kdXN0cnksIGl0IGlzIHJlYXNvbmFibGUgdG8gc3VnZ2VzdCB0aGF0IG1vYmlsZSBpbmR1c3RyeSBoYXMgYSBoaWdoZXIgcmVsYXRpdmUgZGV2ZWxvcG1lbnQgaW4gQ3lwcnVzIHRoYW4gaW4gb3RoZXIgTWlkZGxlIEVhc3QgY291bnRyaWVzLCB3aGljaCBpcyBjb25zaXN0ZW50IHdpdGggdGhlIGVhcmxpZXIgcmVhc29uaW5nIHRoYXQgQ3lwcnVzIGhhdmUgcHJvc3Blcm91cyB0b3VyaXNtLiBIb3dldmVyLCB0aGVyZSBhcmUgc3RpbGwgb3RoZXIgcG9zc2libGUgZXhwbGFuYXRpb25zIGZvciB0aGlzIHBhdHRlcm4sIGZvciBleGFtcGxlLCB0aGUgZGF0YSBpdHNlbGYgbWlnaHQgY29tZSBmcm9tIGEgc2luZ2xlIGNhcnJpZXIsIHdoaWNoIGNvdWxkIGJlIGJhc2VkIGluIEN5cHJ1cy4gVGhlbiwgdGhlIGh1Z2Ugdm9sdW1lIG9mIHJlY29yZHMgaW4gQ3lwcnVzIHdvdWxkIG1ha2UgbW9yZSBzZW5zZSwgc2luY2UgaW4gb3RoZXIgY291bnRyaWVzLCBwZW9wbGUgbWF5IHVzZSBvdGhlciBtYWpvciBjYXJyaWVycyBhbmQgc3VjaCBncmVhdCBudW1iZXIgb2YgcmVjb3JkcyBpcyBpbnZpc2libGUgaW4gdGhpcyBkYXRhc2V0Lg0KDQpBZnRlciBjb21wYXJpbmcgdGhlIGRhdGEgYWNyb3NzIGNvdW50cmllcywgd2Ugbm93IGNhbiBjb21wYXJlIHRoZW0gYWNyb3NzIHRpbWUuDQoNCkZpcnN0LCB3ZSB3YW50IHRvIHNlZSBob3cgdGhlIG51bWJlciBvZiByZWNvcmRzIHZhcmllcyBhY3Jvc3MgdGltZSwgc28gd2UgcGxvdCB0d28gYW5pbWF0aW9uIGludGVyYWN0aXZlIGdyYXBocyB0aGF0IGV2b2x2ZSBhcyB0aW1lIGdvZXMgYnkuIA0KDQpUaGlzIGlzIGEgc2NyZWVuIHNob3Qgb2YgdGhlIGludGVyYWN0aXZlIG1hcChJbiBbc2hpbnkgYXBwXShodHRwczovL3poaXJ1aS5zaGlueWFwcHMuaW8vbW9iaWxlX3NpZ25hbC8pLCBpdCBpcyAqKk51bWJlciBvZiBSZWNvcmRzIGluIE1pZGVhc3QqKiBtYXAgdGFiKToNCg0KIVtdKC4vR0lGL01pZGVhc3QgTWFwLmdpZikNCg0KDQpXZSB1c2UgbGVhZmxldCB0byBkcmF3IHRoaXMgQ2hvcm9wbGV0aHMgZ3JhcGguIFdlIGRvd25sb2FkIGdlb2pzb24gZGF0YSBvZiB0aGUgd29ybGQgY291bnRyeSBwb2x5Z29ucywgdXNlIGdlb2pzb25pbzo6Z2VvanNvbl9yZWFkKCkgdG8gcmVhZCBpbiB0aGUgZGF0YSBhcyBhIFNwYXRpYWxQb2x5Z29uc0RhdGFGcmFtZSBvYmplY3QsIGFuZCB0aGVuIGNvbmNhdGVuYXRlIG91ciBjb3VudCBkYXRhIGludG8gdGhpcyBvYmplY3QuIEJlY2F1c2UgdGhlIHZhbHVlIG9mIG51bWJlciBvZiByZWNvcmRzIHZhcnkgYSBsb3QgYWNyb3NzIGNvdW50cmllcywgd2UgaGF2ZSB0byB1c2UgdW5ldmVuIGNvbG9yIGJhciB0byB2aXN1YWxpemUgdGhlIHZhbHVlcy4gV2UgYWRkIGEgc2xpZGVyIHNlbGVjdG9yIHRvIHRoZSBncmFwaCwgdG8gc2VsZWN0IHRoZSBob3VyIG9mIHRoZSBkYXRhLiBXZSBhbHNvIG1ha2UgdGhlIGdyYXBoIGFuaW1hdGlvbiwgd2hpY2ggY29udHJvbGxlZCBieSBhICJwbGF5L3BhdXNlIiBidXR0b24uIFdlIHVzZSBhZGRQb2x5Z29ucygpIGZ1bmN0aW9uIHRvIGRyYXcgU3BhdGlhbFBvbHlnb25zRGF0YUZyYW1lIG9udG8gdGhlIG1hcC4gV2Ugc2V0IG1hbnkgcGFyYW1ldGVycyBpbiB0aGlzIGZ1bmN0aW9uIHRvIG1ha2UgdGhpcyBncmFwaCBtb3JlIHByZXR0eSwgc3VjaCBhcyBtYWtpbmcgdGhlIHBvbHlnb24gdHJhbnNwYXJlbnQgaW4gb3JkZXIgdG8gc2VlIHRoZSBjb3VudHJ5IG5hbWUgaW4gdGhlIGJhY2tncm91bmQgY2xlYXJseSwgbWFrZSBjb3VudHJ5IGJvdW5kYXJ5IHdoaXRlIGFuZCBkYXNoZWQgbGluZSBpbiBvcmRlciB0byBtYWtlIGl0IGxvb2tzIGxpa2UgaGFuZC1tYWRlLCBhbmQgYWRkIGRlc2NyaXB0aW9uIG9mIGVhY2ggY291bnRyeSB3aGVuIHRoZSBjdXJzb3IgYXJlIG9uIHRoYXQgcG9seWdvbi4NCg0KVGhpcyBpcyBhIHNjcmVlbiBzaG90IG9mIHRoZSBpbnRlcmFjdGl2ZSBiYXJjaGFydChJbiBbc2hpbnkgYXBwXShodHRwczovL3poaXJ1aS5zaGlueWFwcHMuaW8vbW9iaWxlX3NpZ25hbC8pLCBpdCBpcyAqKk51bWJlciBvZiBSZWNvcmRzIGluIE1pZGVhc3QqKiBiYXJjaGFydCB0YWIpOg0KDQohW10oLi9HSUYvbnVtYmVyIG1pZGVhc3QuZ2lmKQ0KDQoNClRoaXMgZ3JhcGggaXMgdmVyeSBzaW1pbGFyIHRvIHRoZSBzdGF0aWMgYmFyIGNoYXJ0IG9mIHRoZSBudW1iZXIgb2YgcmVjb3JkcywgZXhjZXB0IHdlIGFkZCBhbm90aGVyIGRpbWVuc2lvbiBvZiBob3VyIGludG8gdGhpcyBncmFwaCB0byBtYWtlIGl0IGFuaW1hdGlvbi4gV2UgYWxzbyBhZGQgYSBzbGlkZXIgc2VsZWN0b3IgdG8gdGhlIGdyYXBoLCB0byBzZWxlY3QgdGhlIGhvdXIgb2YgdGhlIGRhdGEgYW5kIHVzZSBmaWx0ZXIoKSBmdW5jdGlvbiB0byBzZWxlY3QgdGhlIGRhdGEgb2YgdGhhdCBob3VyLCBhbmQgdGhlbiByZW5kZXIgdGhlIHBsb3QuIA0KDQpGcm9tIHRoZSBwbG90IGFib3ZlLCB3ZSBjYW4gc2VlIHRoYXQgdGhlIG51bWJlciBvZiByZWNvcmRzIHRvdWNoIHRoZSBib3R0b20gYXQgZGF3biwgc3RhcnQgdG8gaW5jcmVhc2UgYXMgdGltZSBnb2VzIGJ5LCBhbmQgdGhlbiByZWFjaCB0aGUgcGVhayBhdCBtaWRuaWdodCwgd2hpY2ggbWFrZXMgcGVyZmVjdCBzZW5zZS4gQXQgZGF3biwgdGhlcmUgYXJlIGZldyBwZW9wbGUgc3RpbGwgYXdha2UsIHdoaWxlIGFsbW9zdCBhbGwgcGVvcGxlIGFyZSBhc2xlZXAuIFRoZW4sIHdoZW4gcGVvcGxlIHN0YXJ0IHRvIGdldCB1cCBhbmQgYmVnaW4gdGhlIGRheSwgcGVvcGxlIHN0YXJ0IHRvIHVzZSBtb2JpbGUgZm9yIGFsbCBraW5kcyBvZiB0aGluZ3MuIEhvd2V2ZXIsIGluIHRoZSBkYXl0aW1lLCBwZW9wbGUgaGF2ZSB0byB3b3JrLCBzdHVkeSBvciBqdXN0IHJ1biBlcnJhbmRzLCBzbyBhZnRlciB0aGV5IGdldHRpbmcgb2ZmIHdvcmssIGZpbmlzaGluZyBzY2hvb2x3b3JrIGZvciB0aGUgZGF5LCBoYXZpbmcgYSBncmVhdCBkaW5uZXIgd2l0aCBmYW1pbHksIHB1dHRpbmcgdGhlaXIgY2hpbGRyZW4gdG8gYmVkLCB0aGUgbW9iaWxlIHVzYWdlIHBlYWsgb2NjdXJzLg0KDQojIyNBY2N1cmFjeQ0KQmVzaWRlcyB0aGUgbnVtYmVyIG9mIHJlY29yZHMsIHRoZSBvdGhlciBpbnRlcmVzdGluZyBmZWF0dXJlIGluIHRoaXMgZGF0YSBzZXQgaXMgdGhlIGFjY3VyYWN5LiBJdCBjYW4gYmUgc2VlbiBhcyB0aGUgJ2NvbmZpZGVuY2UgaW50ZXJ2YWwnIG9mIHRoZSBiYXNlIHN0YXRpb25zIGluIGRpZmZlcmVudCBjb3VudHJpZXMsIHdoaWNoIGNhbiBhbHNvIGJlIGFmZmVjdGVkIGJ5IHRoZSBtb2JpbGUgZGV2aWNlIGl0c2VsZi4NCmBgYHtyLGZpZy53aWR0aD04fQ0KeF9ncm91cF9hY2N1cmFjeSA8LSB4ICU+JSANCiAgZmlsdGVyKFRpbWVzdGFtcD5hcy5EYXRlKCcyMDE2LTEyLTEyIDAwOjAwOjAwIFVUQycpKSAlPiUgDQogIGdyb3VwX2J5KENPVU5UUlkpICU+JSANCiAgc3VtbWFyaXNlKG1lYW5fQWNjdXJhY3k9bWVhbihBY2N1cmFjeSksc3RfYWNjdXJhY3k9c2QoQWNjdXJhY3kpKQ0KKHhfZ3JvdXBfYWNjdXJhY3kgJT4lIA0KICBhcnJhbmdlKG1lYW5fQWNjdXJhY3kpICU+JSANCiAgZ2dwbG90KGFlcyh5PW1lYW5fQWNjdXJhY3kseD1hc19mYWN0b3IoQ09VTlRSWSkpKSsNCiAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiLGZpbGw9J3NreWJsdWUyJykrDQogIGNvb3JkX2ZsaXAoKSsNCiAgeWxhYignTWVhbiBBY2N1cmFjeScpKw0KICB4bGFiKCdDb3VudHJ5IE5hbWUnKSsNCiAgZ2d0aXRsZSgnTWVhbiBBY2N1cmFjeSBieSBDb3VudHJ5JykpICU+JSANCiAgZ2dwbG90bHkNCmBgYA0KDQpJbiBvcmRlciB0byBkcmF3IHRoaXMgZ3JhcGgsIGZpcnN0IHdlIGZpbHRlciB0aGUgZGF0YSB0byBkcm9wIHRoZSByb3dzIHRoYXQgZG9lcyBub3QgYmVsb25nIHRvIHRoZXNlIHRocmVlIGRheXMuIFRoZW4gd2UgZ3JvdXAgdGhlIGRhdGEgYnkgY291bnRyeSBhbmQgY2FsY3VsYXRlIHRoZSBtZWFuIGFuZCBzdGFuZGFyZCBkZXZpYXRpb24gb2YgYWNjdXJhY3kgb2YgZWFjaCBjb3VudHJ5LiBXZSBhbHNvIHNvcnQgdGhlIGJhciBjaGFydCBieSB0aGUgbWVhbiBhY2N1cmFjeS4NCg0KRnJvbSB0aGUgcGxvdCBhYm92ZSwgdGhlcmUgYXJlIGZvdXIgY291bnRyaWVzIGhhdmUgbWVhbiBhY2N1cmFjeSBvdmVyIDIwMDAgbWV0ZXJzOiBMaWJ5YSwgSXJhcSwgU291dGggU3VkYW4gYW5kIERlbW9jcmF0aWMgUmVwdWJsaWMgb2YgQ29uZ28uIEFsbCBvZiB0aGVtIGFyZSBpbiB1cGhlYXZhbCBvciBleHBlcmllbmNlZCBodWdlIHR1cmJ1bGVuY2UuIFRoZSBzbW9rZSBmcm9tIHRoZSB3YXJzIGNvdWxkIHJlYWxseSBhZmZlY3QgdGhlIG1vYmlsZSBzaWduYWwsIGhlbmNlLCBhZmZlY3QgdGhlIGFjY3VyYWN5LiBBZGRpdGlvbmFsbHksIGluIHVuc3RhYmxlIGNvdW50cmllcyBsaWtlIHRoZXNlLCB0aGVyZSBpcyBubyBleHRyYSBtb25leSwgcGVvcGxlLCByZXNvdXJjZXMgb3IgbW90aXZhdGlvbnMgZm9yIHNvbWVvbmUgdG8gZGV2ZWxvcCB0aGUgbW9iaWxlIGluZHVzdHJ5LCBib3RoIG1vYmlsZSBwaG9uZXMgYW5kIGJhc2Ugc3RhdGlvbnMuIFNvIHRoZXkgYXJlIGV4cGVjdGVkIHRvIGhhdmUgaGlnaGVzdCBhY2N1cmFjeS4gT24gdGhlIG90aGVyIGhhbmQsIEN5cHJ1cyBhZ2FpbiBiZWF0cyBvdGhlciBjb3VudHJpZXMgdG8gYmUgdGhlIGJlc3QgaW4gdGVybXMgb2YgYWNjdXJhY3kgaW4gTWlkZGxlIEVhc3QuIEJlc2lkZXMgaXRzIHN0YWJsZSBwb2xpdGljYWwgc2l0dWF0aW9uLCB0aGUgbWFqb3JpdHkgb2YgdGhlIGNvdW50cnkgaXMgcGxhaW4sIHdoaWNoIGlzIGJlbmVmaWNpYWwgZm9yIGJhc2Ugc3RhdGlvbnMuIEZ1cnRoZXJtb3JlLCBhcyBhIHBvcHVsYXIgdG91cmlzdCBkZXN0aW5hdGlvbiwgaXQgaGFzIHRoZSBtb3RpdmF0aW9uIHRvIGJ1aWxkIGEgYmV0dGVyIGVudmlyb25tZW50IGZvciBpbnRlcm5ldCB1c2VycyBpbiBvcmRlciB0byBhdHRyYWN0IG1vcmUgdG91cmlzdHMuDQoNCkFsc28gd2UgY2FuIHZpc3VhbGl6ZSB0aGUgbWVhbiBhY2N1cmFjeSBjaGFuZ2UgYnkgdGltZS4NCg0KVGhpcyBpcyBhIHNjcmVlbiBzaG90IG9mIHRoZSBpbnRlcmFjdGl2ZSBiYXJjaGFydChJbiBbc2hpbnkgYXBwXShodHRwczovL3poaXJ1aS5zaGlueWFwcHMuaW8vbW9iaWxlX3NpZ25hbC8pLCBpdCBpcyAqKk1lYW4gQWNjdXJhY3kgaW4gTWlkZWFzdCoqIGJhcmNoYXJ0IHRhYik6DQoNCiFbXSguL0dJRi9tZWFuIGFjY3VyYWN5IG1pZGVhc3QuZ2lmKQ0KDQpUaGlzIGdyYXBoIGlzIHZlcnkgc2ltaWxhciB0byB0aGUgc3RhdGljIGJhciBjaGFydCBvZiB0aGUgbWVhbiBhY2N1cmFjeSwgZXhjZXB0IHdlIGFkZCBhbm90aGVyIGRpbWVuc2lvbiBvZiBob3VyIGludG8gdGhpcyBncmFwaCB0byBtYWtlIGl0IGFuaW1hdGlvbi4gV2UgYWxzbyBhZGQgYSBzbGlkZXIgc2VsZWN0b3IgdG8gdGhlIGdyYXBoLCB0byBzZWxlY3QgdGhlIGhvdXIgb2YgdGhlIGRhdGEgYW5kIHVzZSBmaWx0ZXIoKSBmdW5jdGlvbiB0byBzZWxlY3QgdGhlIGRhdGEgb2YgdGhhdCBob3VyLCBhbmQgdGhlbiByZW5kZXIgdGhlIHBsb3QuIA0KDQpJdCBkb2VzIG5vdCBzZWVtIHRvIGJlIGEgY2xlYXIgcGF0dGVybiBvZiBob3cgdGhlIG1lYW4gYWNjdXJhY3kgZXZvbHZlIG92ZXIgdGltZSwgYnV0IHdlIGNhbiBzZWUgdGhhdCANClNvdXRoIFN1ZGFuIGFuZCBMaWJ5YSB2YXJpZXMgYSBsb3QgYWNyb3NzIHRpbWUuIFNvIHdlIHBsb3QgdGhlIHN0YW5kYXJkIGRldmlhdGlvbiBvZiB0aGUgYWNjdXJhY3kgYWNyb3NzIGNvdW50cnkgYW5kIGFjcm9zcyB0aW1lIHRvIGhhdmUgYSBtb3JlIGNsZWFyIHZpZXcuDQoNCmBgYHtyLGZpZy53aWR0aD04fQ0KKHhfZ3JvdXBfYWNjdXJhY3kgJT4lIA0KICBhcnJhbmdlKHN0X2FjY3VyYWN5KSAlPiUgDQogIGdncGxvdChhZXMoeT1zdF9hY2N1cmFjeSx4PWFzX2ZhY3RvcihDT1VOVFJZKSkpKw0KICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIsZmlsbD0nc2t5Ymx1ZTInKSsNCiAgY29vcmRfZmxpcCgpKw0KICB5bGFiKCdTdGFuZGFyZCBEZXZpYXRpb24gb2YgQWNjdXJhY3knKSsNCiAgeGxhYignQ291bnRyeSBOYW1lJykrDQogIGdndGl0bGUoJ1N0YW5kYXJkIERldmlhdGlvbiBvZiBBY2N1cmFjeSBieSBDb3VudHJ5JykpICU+JSANCiAgZ2dwbG90bHkNCmBgYA0KDQpXZSB1c2UgdGhlIGRhdGEgZnJhbWUgd2UgZ2VuZXJhdGVkIGZyb20gdGhlIHByZXZpb3VzIHBhcnQgYXMgaW5wdXQgdG8gcGxvdCB0aGlzIGdyYXBoLiBXZSBvcmRlcmVkIHRoZSBjb3VudHJpZXMgYnkgdGhlIHZhbHVlIG9mIHN0YW5kYXJkIGRldmlhdGlvbiBvZiBhY2N1cmFjeSBhbmQgZHJhdyB0aGUgYmFyIGNoYXJ0Lg0KDQpTb3V0aCBTdWRhbiBoYXMgdGhlIGhpZ2hlc3Qgc3RhbmRhcmQgZGV2aWF0aW9uLCBmb2xsb3dlZCBieSBMaWJ5YSBhbmQgU3lyaWFuLCB3aGljaCBoYXZlIG11Y2ggdG8gZG8gd2l0aCB0aGVpciB1bnN0YWJsZSBwb2xpdGljYWwgc2l0dWF0aW9ucy4gSG93ZXZlciwgdGhlIHJlc3Qgb2YgY291bnRyaWVzIGhhdmUgc2ltaWxhcmx5IGhpZ2ggc3RhbmRhcmQgZGV2aWF0aW9uLiBTbyBpdCBpcyBwb3NzaWJsZSB0aGF0IE1pZGRsZSBFYXN0IGNvdW50cmllcyBnZW5lcmFsbHkgZG8gbm90IGhhdmUgc29waGlzdGljYXRlZCB0ZWNobmlxdWVzIGFuZCB3ZWxsLWRldmVsb3BlZCBpbmZyYXN0cnVjdHVyZSwgd2hpY2ggbGVhZHMgdG8gdGhlIHBvb3IgYWNjdXJhY3kgd2l0aCBncmVhdCBzdGFuZGFyZCBkZXZpYXRpb24uDQoNCmBgYHtyLGZpZy53aWR0aD04fQ0KKHggJT4lIA0KICBmaWx0ZXIoVGltZXN0YW1wPmFzLkRhdGUoJzIwMTYtMTItMTIgMDA6MDA6MDAgVVRDJykpICU+JSANCiAgbXV0YXRlKEhvdXI9aG91cihUaW1lc3RhbXApKSAlPiUgDQogIGdyb3VwX2J5KEhvdXIpICU+JSANCiAgc3VtbWFyaXNlKHN0X2FjY3VyYWN5PXNkKEFjY3VyYWN5KSkgJT4lIA0KICBtdXRhdGUoaG91cj1Ib3VyICU+JSBhcy5jaGFyYWN0ZXIpICU+JSANCiAgZ2dwbG90KGFlcyh5PXN0X2FjY3VyYWN5LHg9aG91ciAlPiUgYXNfZmFjdG9yKSkrDQogIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5IixmaWxsPSdza3libHVlMicpKw0KICBjb29yZF9mbGlwKCkrDQogIHlsYWIoJ1N0YW5kYXJkIERldmlhdGlvbiBvZiBBY2N1cmFjeScpKw0KICB4bGFiKCdIb3VyJykrDQogIGdndGl0bGUoJ1N0YW5kYXJkIERldmlhdGlvbiBvZiBBY2N1cmFjeSBhY3Jvc3MgVGltZScpKSAlPiUgDQogIGdncGxvdGx5DQpgYGANCkluIG9yZGVyIHRvIGRyYXcgdGhpcyBncmFwaCwgZmlyc3Qgd2UgZmlsdGVyIHRoZSBkYXRhIHRvIGRyb3AgdGhlIHJvd3MgdGhhdCBkb2VzIG5vdCBiZWxvbmcgdG8gdGhlc2UgdGhyZWUgZGF5cy4gVGhlbiB3ZSBncm91cCB0aGUgZGF0YSBieSBob3VyIGFuZCBjYWxjdWxhdGUgdGhlIHN0YW5kYXJkIGRldmlhdGlvbiBvZiBhY2N1cmFjeSBvZiBlYWNoIGhvdXIuIFdlIGFsc28gaGF2ZSB0byB1c2UgYXNfZmFjdG9yIHRvIG1haW50YWluIHRoZSBudW1lcmljYWwgb3JkZXIgb2YgdGhlIGhvdXJzLCBvciBpbiBnZ3Bsb3QgYWZ0ZXIgd2UgY29udmVydCB0aGUgaG91ciBpbnRvIGNoYXJhY3RlciwgaXQgd2lsbCBhcnJhbmdlIDEwLCAxMSBhbmQgMTIgYWZ0ZXIgMSwgbm90IGFmdGVyIDkuDQoNCkZyb20gdGhlIGVhcmxpZXIgYW5hbHlzaXMgb24gdGhlIG51bWJlciBvZiByZWNvcmRzIGFjcm9zcyB0aW1lLCB3ZSBuYXR1cmFsbHkgYXNzdW1lZCB0aGF0IHRoZSBhY2N1cmFjeSBoYXMgdGhlIHNpbWlsYXIgcGF0dGVybi4gSG93ZXZlciwgYmFzZWQgb24gdGhlIHBsb3QgYWJvdmUsIHRoZXJlIGlzIHJlYWxseSBubyBzaWduaWZpY2FudCBkaWZmZXJlbmNlIGluIHN0YW5kYXJkIGRldmlhdGlvbiBvZiBhY2N1cmFjeSBhY3Jvc3MgdGltZS4gU28gdGhlcmUgaXMgYSBzdHJvbmcgaW5kaWNhdGlvbiB0aGF0IGFjY3VyYWN5IG1haW5seSBkZXBlbmRzIG9uIGJhc2Ugc3RhdGlvbnMgaXRzZWxmIG90aGVyIHRoYW4gaG93IG1hbnkgcGVvcGxlIGFyZSB1c2luZyB0aGUgbW9iaWxlLiANCg0KIyNSdXNzaWENCiMjI051bWJlciBvZiBSZWNvcmRzIGFuZCBBY2N1cmFjeQ0KRmlyc3Qgd2UgZHJhdyBhIGJhciBjaGFydCBvZiB0aGUgbnVtYmVyIG9mIHJlY29yZHMgcGVyIGhvdXINCmBgYHtyLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KWDIwMTZfMTJfMTBiX25ldyA8LSByZWFkX2NzdigiQzovVXNlcnMvd2FuZ18vRGVza3RvcC8yMDE2LTEyLTEwYl9uZXcuY3N2Iixwcm9ncmVzcz1GKQ0KWDIwMTZfMTJfMTFiX25ldyA8LSByZWFkX2NzdigiQzovVXNlcnMvd2FuZ18vRGVza3RvcC8yMDE2LTEyLTExYl9uZXcuY3N2Iixwcm9ncmVzcz1GKQ0KWDIwMTZfMTJfMTJiX25ldyA8LSByZWFkX2NzdigiQzovVXNlcnMvd2FuZ18vRGVza3RvcC8yMDE2LTEyLTEyYl9uZXcuY3N2Iixwcm9ncmVzcz1GKQ0KeCA8LSBiaW5kX3Jvd3MoWDIwMTZfMTJfMTBiX25ldyxYMjAxNl8xMl8xMWJfbmV3LFgyMDE2XzEyXzEyYl9uZXcpDQpgYGANCg0KYGBge3IsZmlnLndpZHRoPTh9DQooeCAlPiUgDQogIG11dGF0ZShIb3VyPWhvdXIoYFRpbWUgU3RhbXBgKSkgJT4lIA0KICBncm91cF9ieShIb3VyKSAlPiUgDQogIHN1bW1hcmlzZShjb3VudD1uKCkpICU+JSANCiAgZ2dwbG90KGFlcyh5PWNvdW50LHg9SG91ciAlPiUgYXMuY2hhcmFjdGVyKSkrDQogIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5IixmaWxsPSdza3libHVlMicpKw0KICBjb29yZF9mbGlwKCkrDQogIHlsYWIoJ051bWJlciBvZiBSZWNvcmRzJykrDQogIHhsYWIoJ0hvdXInKSsNCiAgZ2d0aXRsZSgnTnVtYmVyIG9mIFJlY29yZHMgYWNyb3NzIFRpbWUnKSkgJT4lIA0KICBnZ3Bsb3RseQ0KYGBgDQpUaGUgZ3JhcGggcGxvdHRpbmcgcHJvY2VzcyBpcyBhbG1vc3QgdGhlIHNpbWlsYXIgdG8gdGhlIGNvdW50ZXJwYXJ0IGluIE1pZGVhc3QuIFRoZSBvbmx5IGRpZmZlcmVuY2UgaXMgdGhhdCB0aGVyZSBpcyBubyBkYXRhIHRoYXQgaXMgbm90IGluIHRoYXQgZGF5LCBzbyB3ZSBkbyBub3QgbmVlZCB0byBjbGVhbiBpdCBmaXJzdC4NCg0KVGhlIGludGVybmV0IHVzYWdlIGJlaGF2aW9yIGluIFJ1c3NpYSBpcyB2ZXJ5IGRpZmZlcmVudCBmcm9tIHRoYXQgaW4gTWlkZWFzdC4gVGhlIG51bWJlciBvZiB1c2VycyBwZWFrcyBpbiB0aGUgYWZ0ZXJub29uLCBkZWNyZWFzZXMgYXMgdGltZSBnb2VzIGJ5IGFuZCByZWFjaGVzIHRoZSBib3R0b20gYXQgbmlnaHQsIHdoaWNoIGlzIHRoZSBvcHBvc2l0ZSBvZiB0aGUgTWlkZWFzdC4gSXQgbWlnaHQgYmUgdGhhdCBSdXNzaWFucyB0ZW5kIHRvIHN0YXJ0IHRoZWlyIGRheSBlYXJseSwgYW5kIGZpbmlzaCB0aGVpciBqb2JzIGFyb3VuZCB0aGUgbm9vbi4gVGhlbiBhZnRlciB0aGUgZWFybHkgbHVuY2gsIHRoZXkgbGlrZSB0byBoYXZlIHNvbWUgYWZ0ZXJub29uIHRlYSB3aXRoIGNvbGxlYWd1ZXMgb3IgZnJpZW5kcywgd2hlcmUgdGhleSBjaGF0LCBsYXVnaCwgZG8gc2VsZmllcywgcG9zdCBvbiBzb2NpYWwgbWVkaWEgbGlrZSBGYWNlYm9vayBvciBJbnN0YWdyYW0uIEFsc28sIFJ1c3NpYW5zIGFyZSBraW5kIG9mIHRyYWRpdGlvbmFsLCBzbyBhZnRlciB3b3JrIG9yIHNjaG9vbCwgdGhleSB0ZW5kIHRvIGdvIGhvbWUgYW5kIGhhdmUgc29tZSBxdWFsaXR5IHRpbWUgd2l0aCBmYW1pbGllcywgbGlrZSB3YXRjaGluZyBhIG1vdmllIHRvZ2V0aGVyLCByZWFkaW5nIGJvb2tzIHRvIGNoaWxkcmVuLCBvciBldmVuIHRha2luZyBhIGRhbmNlIGxlc3NvbiB3aXRoIHNwb3VzZSBldGMuIA0KDQpXZSBjYW4gYWxzbyBzZWUgdGhpcyByZWxhdGlvbnNoaXAgd2hlbiB3ZSBwbG90IHRoYXQgb24gdGhlIG1hcC4NClRoaXMgaXMgYSBzY3JlZW4gc2hvdCBvZiB0aGUgYW5pbWF0aW9uIG1hcCAoSW4gW3NoaW55IGFwcF0oaHR0cHM6Ly96aGlydWkuc2hpbnlhcHBzLmlvL21vYmlsZV9zaWduYWwvKSwgaXQgaXMgKipBY2N1cmFjeSBpbiBSdXNzaWEqKiBtYXAgdGFiKToNCg0KIVtdKC4vR0lGL2FjY3VyYWN5IHJ1c3NpYS5naWYpDQoNCkluIHRoaXMgZ3JhcGggd2UgaGF2ZSBiaWxsaW9ucyBvZiBwb2ludHMgdG8gdmlzdWFsaXplLCB3aGVuIHdlIHRyeSB0byB1c2UgaW50ZXJhY3RpdmUgZ3JhcGhpbmcgdG8gdmlzdWFsaXplIGl0LCB0aGUgUiB3aWxsIGNyYXNoIGhhbGZ3YXksIHRodXMgd2UgaGF2ZSB0byB1c2Ugc3RhdGljIGdyYXBoaW5nIG1ldGhvZCB0byBwbG90IHRoZSBtYXAsIGFuZCBjb21iaW5lIHRoZSBtYXAgb3ZlciB0aW1lIHRvIG1ha2UgYW5pbWF0aW9uLiBIZXJlIHdlIHVzZSBnZ21hcCBwYWNrYWdlIHRvIGRyYXcgdGhlIHN0YXRpYyBtYXAuIFRoZSByYW5nZSBvZiB0aGUgQWNjdXJhY3kgaXMgdmVyeSBodWdlLCBzbyB3ZSB1c2UgbG9nLXRyYW5zZm9ybWF0aW9uIG9uIHRoZSBBY2N1cmFjeSBpbiBvcmRlciB0byBnZXQgYSBtb3JlIGNsZWFyIGNvbG9yIHZpc3VhbGl6YXRpb24uIEl0IHdpbGwgdG9vayBzZXZlcmFsIG1pbnV0ZXMgdG8gZHJhdyBhIG1hcCBmb3Igb25lICBvZiB0aGUgdGVuIGhvdXJzLCBzbyB3ZSB1c2UgcGFyYWxsZWwgY29tcHV0aW5nIG1ldGhvZCBpbiBSIHRvIHBsb3QgdGhlIG1hcCBpbiBwYXJhbGxlbCBpbiBvcmRlciB0byBwbG90IHRoZSBtYXAgZmFzdGVyLiBXZSBzYXZlIGVhY2ggbWFwIGFzIHBuZywgYW5kIHJlYWQgZWFjaCBob3VyJ3MgbWFwIGluIHNoaW55IHVzaW5nIGFuIGhvdXIgc2xpZGVyIHNlbGVjdG9yLg0KDQpBcyBzaG93biBpbiB0aGUgbWFwLCB0aGUgbW9iaWxlIHBob25lIHVzZXJzIGFyZSBhbGwgY2x1c3RlcmVkIGluIHRoZSBzb3V0aCBlYXN0IHBhcnQgb2YgdGhlIGNvdW50cnksIGJ1dCB0aGVyZSBpcyBldmVuIG5vIHNpbmdsZSByZXF1ZXN0IGluIG1vc3QgcGFydCBvZiB0aGUgU2liZXJpYS4gSXQgaXMgdGhlIHNhbWUgYXMgd2UgZXhwZWN0ZWQgc2luY2UgdGhlIG1ham9yaXR5IG9mIFJ1c3NpYW5zIGxpdmUgaW4gdGhlIFNvdXRoZWFzdGVybiByZWdpb24sIHdoaWxlIFNpYmVyaWEgaXMgYmFyZSBkdWUgdG8gaXRzIHVuYmVhcmFibGUgd2VhdGhlci4NCg0KQWxzbywgd2UgY2FuIHNlZSB0aGUgcGF0dGVybiBkaXNjdXNzZWQgZWFybGllciBjbGVhcmx5IHNob3dpbmcgaW4gdGhlIG1hcDogdGhlIG51bWJlciBvZiBkb3RzIHBlYWtzIGluIHRoZSBhZnRlcm5vb24gYW5kIGRlY3JlYXNlcyBhcyB0aW1lIGdvZXMgYnkuDQoNCkluIGFkZGl0aW9uLCB3ZSBjYW4gc2VlIGZyb20gdGhlIG1hcCB0aGF0IGluIHRoZSBzb3V0aCBlYXN0IHBhcnQgb2YgdGhlIGNvdW50cnkgdGhlcmUgYXJlIG1hbnkgcmVkIGRvdHMsIHdoaWxlIGluIHRoZSBub3J0aCBlYXN0IHBhcnQgbW9zdCBvZiB0aGUgZG90cyBhcmUgbGlnaHQgeWVsbG93LiBUbyBxdWFudGlmeSB0aGlzIHN0YXRlbWVudCwgd2UgY2FuIGdlbmVyYXRlIGEgbGluZWFyIHJlZ3Jlc3Npb24gdG8gc2VlIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBhY2N1cmFjeSBhbmQgbGF0aXR1ZGUgYW5kIGxvbmdpdHVkZS4NCiQkDQogIEFjY3VyYWN5ID0gXGJldGFfezB9ICsgXGJldGFfezF9TGF0aXR1ZGUgKyBcYmV0YV97Mn1Mb25naXR1ZGUgKyBcYmV0YV97M31MYXRpdHVkZVx0aW1lcyBMb25naXR1ZGUgKyBcZXBzaWxvbiANCiQkDQoNCmBgYHtyLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KcmVnIDwtIGJpZ2xtKEFjY3VyYWN5fkxhdHRpdHVkZStMb25naXR1ZGUrTGF0dGl0dWRlKkxvbmdpdHVkZSxkYXRhPXgpDQpyZWcgJT4lIGNvZWZ0ZXN0ICU+JSBhcy50YWJsZSAlPiUga2FibGUNCmBgYA0KDQpJbiB0aGlzIGxpbmVhciByZWdyZXNzaW9uIHdlIHVzZSBiaWdsbSgpIGluc3RlYWQgb2YgbG0oKSBiZWNhdXNlIHdlIGhhdmUgYmlsbGlvbnMgb2YgZGF0YSBwb2ludHMsIHRoZSByZWd1bGFyIGxtKCkgZnVuY3Rpb24gd2lsbCBnZW5lcmF0ZSBhIGh1Z2Ugb2JqZWN0IHVwIHRvIDkgR2lnYWJ5dGVzIGFuZCBlYXQgdXAgYWxsIHRoZSBtZW1vcnkuIEhvd2V2ZXIgYmlnbG0oKSB3aWxsIG92ZXJjb21lIHRoaXMgcHJvYmxlbSBieSBncmFkdWFsbHkgdXBkYXRlIHRoZSBjb2VmZmljaWVudCBtYXRyaXggYnkgY2FsY3VsYXRlIHRoZSBkYXRhIHJvdyBieSByb3cuIA0KDQpBbmQgdGhlIGNvZWZmaWNpZW50IG9mIHRoZSByZWdyZXNzaW9uIHNob3dzIGl0IGlzIHRoZSBzYW1lIGFzIHdlIHZpc3VhbGl6ZWQuIEFzIGxhdGl0dWRlIG9yIGxvbmdpdHVkZSBpbmNyZWFzZXMgMSBkZWdyZWUsIHRoZSBhY2N1cmFjeSB3aWxsIGRlY3JlYXNlIDAuMzYgYW5kIDAuMzIgcmVzcGVjdGl2ZWx5LCBib3RoIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQuIFRoZSBpbnRlcmFjdGl2ZSB0ZXJtIGlzIHNpZ25pZmljYW50IGFzIHdlbGwsIHdoaWxlIHRoZSBtYWduaXR1ZGUgaXMgc28gc21hbGwgYW5kIHdlIGNhbiBpZ25vcmUgdGhhdC4gV2Uga25vdyB0aGF0IHRoZSBsYXRpdHVkZSBjYW4gdmFyeSA0MCBkZWdyZWVzIGFuZCB0aGUgbG9uZ2l0dWRlIGNhbiB2YXJ5IDE0MCBkZWdyZWVzIGFjcm9zcyBSdXNzaWEsIHdoaWNoIGNhbiBicmluZyBzdWJzdGFudGlhbCBkaWZmZXJlbmNlIGluIHRoZSBhY2N1cmFjeSBhY3Jvc3MgYnJvYWQuDQoNCiMjI0ludGVybmV0IFJlcXVlc3QgTW90aW9uIGluIE1vc2Nvdw0KSW4gdGhpcyBwYXJ0LCB3ZSB3YW50IHRvIHZpc3VhbGl6ZSB0aGUgbW90aW9uIG9mIHRoZSBwZW9wbGUgd2hvIG1ha2UgbW9iaWxlIGludGVybmV0IHJlcXVlc3QgaW4gTW9zY293LiBXZSBzZWxlY3QgdGhlIFVzZXIgSURzIHRoYXQgaGF2ZSBiZWVuIHRvIGZpdmUgZmFtb3VzIGxhbmRtYXJrcyBpbiBNb3Njb3csIHdobyBjYW4gYmUgc2VlbiBhcyB0b3VyaXN0cyBpbiBNb3Njb3csIGFuZCB2aXN1YWxpemUgdGhlaXIgbW9iaWxlIGludGVybmV0IHJlcXVlc3QgYWNyb3NzIGhvdXJzIGluIG9uZSBkYXkuIE91ciBkYXRhIG9ubHkgY29udGFpbnMgaG91ciAxMy0yMiwgc28gd2UgY2FuIG9ubHkgdmlzdWFsaXplIHRoZXNlIHRlbiBob3Vycy4gTm90aWNlIHRoYXQgdGhlcmUgbWF5IGJlIGh1bmRyZWRzIG9mIGludGVybmV0IHJlcXVlc3RzLCBidXQgdGhlIG51bWJlciBvZiB1bmlxdWUgSUQgaXMgYXJvdW5kIDIwLCBhbmQgaXMgc2hvd24gb24gdGhlIHVwcGVyLXJpZ2h0IHBhbmVsLiBUaGUgc2VsZWN0b3Igb2YgaG91ciBhbmQgbGFuZG1hcmsgaXMgYWxzbyBpbiB0aGlzIHBhbmVsLiBUaGUgZGVzY3JpcHRpb24gb2YgZWFjaCBkYXRhIHBvaW50IHdpbGwgYmUgc2hvd24gYWZ0ZXIgdGhlIGljb24gb2YgdGhhdCBwb2ludCBpcyBjbGlja2VkLCB3aGljaCB3aWxsIGJlIFVzZXIgSUQgYW5kIFRpbWUgU3RhbXAuICANCg0KVGhpcyBpcyBhIHNjcmVlbiBzaG90IG9mIHRoZSBpbnRlcmFjdGl2ZSBtYXAgKEluIFtzaGlueSBhcHBdKGh0dHBzOi8vemhpcnVpLnNoaW55YXBwcy5pby9tb2JpbGVfc2lnbmFsLyksIGl0IGlzICoqSW50ZXJuZXQgUmVxdWVzdCBpbiBNb3Njb3cqKiBtYXAgdGFiKToNCg0KIVtdKC4vR0lGL21vdGlvbiBydXNzaWEuZ2lmKQ0KDQpUbyBkcmF3IHRoaXMgbWFwIGFuZCByZWFkIGl0IGNsZWFybHksIHdlIGhhdmUgdG8gZmluZCBhIG1hcCB0aGF0IHByb3ZpZGUgRW5nbGlzaCBsb2NhdGlvbiBuYW1lcyBvbiBSdXNzaWEgdGVycml0b3J5LiBVbmZvcnR1bmF0ZWx5IGFsbCB0aGUgZGVmYXVsdCBtYXAgcHJvdmlkZXJzIGluIGxlYWZsZXQgZG9lcyBub3QgaGF2ZSBFbmdsaXNoIGxvY2F0aW9uIG5hbWVzIG9uIGZvcmVpZ24gY291bnRyaWVzLCB0aHVzIHdlIHVzZSBNYXBib3ggYXMgb3VyIGN1c3RvbSBtYXAgcHJvdmlkZXIgdG8gcGxvdCB0aGlzIG1hcC4gV2Ugd2FudCB0byBzZWUgdGhlIGNsdXN0ZXJuZXNzIG9mIHRoZSBpbnRlcm5ldCByZXF1ZXN0LCBzbyB3ZSB1c2UgbWFya2VyIGNsdXN0ZXJzIHdoZW4gZHJhd2luZyBpbmRpdmlkdWFsIHBvaW50cyBvbiB0byB0aGUgbWFwLCB0aGV5IHdpbGwgc2hvdyB0aGUgbnVtYmVyIG9mIHBvaW50cyBpbiBvbmUgY2x1c3Rlci4gV2hlbiB3ZSB6b29tIGluLCB0aGUgY2x1c3RlciB3aWxsIHNwcmVhZCBvdXQgYW5kIGZpbmFsbHkgc2hvd2luZyBpbmRpdmlkdWFsIHBvaW50cy4gDQoNCkZpcnN0IGxldCB1cyBsb29rIGF0IHRoZSBnZW5lcmFsIHBhdHRlcm4gb2YgaW50ZXJuZXQgcmVxdWVzdCBvZiB0aG9zZSBwZW9wbGUgd2hvIGhhcyBiZWVuIGludG8gdGhlc2UgZml2ZSBsYW5kbWFya3MuIFRoZSBudW1iZXJzIG9mIHVuaXF1ZSBJRCBhbmQgdGhlIG51bWJlcnMgb2YgcmVxdWVzdCBwZWFrcyBhdCBhZnRlcm5vb24gYW5kIGhpdHMgdGhlIGJvdHRvbSBhdCBuaWdodCB3aXRoIG5vIHJlY29yZCBpbiBob3VyIDIyLiBUaGlzIG1pZ2h0IGJlIGR1ZSB0byBhdCBuaWdodCB0b3VyaXN0cyBnbyBiYWNrIHRvIHRoZWlyIGhvdGVsIGFuZCBjb25uZWN0IHRvIHRoZSBob3RlbCBXaUZpLCBzbyB0aGV5IGRvIG5vdCBuZWVkIHRvIG1ha2UgaW50ZXJuZXQgcmVxdWVzdCB2aWEgdGVsZWNvbS4gIA0KDQpUaGUgbmV4dCB0aGluZyB0aGF0IGlzIHdvcnRoeSBub3RpY2luZyBpcyB0aGVyZSBhcmUgdHdvIGFpcnBvcnRzIGluIE1vc2NvdzogVm51a292byBJbnRlcm5hdGlvbmFsIGFpcnBvcnQgb24gdGhlIGJvdHRvbS1sZWZ0IG9mIHRoZSBtYXAsIGFuZCB0aGUgU2hlcmVtZXR5ZXZvIEludGVybmF0aW9uYWwgQWlycG9ydCBvbiB0aGUgdXBwZXItbGVmdCBvZiB0aGUgbWFwLiBBbG1vc3QgYWxsIHRoZSBpbnRlcm5ldCByZXF1ZXN0cyBhcmUgZHVyaW5nIGhvdXIgMTMgdG8gMTcuIEluIGVhY2ggb2YgdGhlc2UgaG91cnMgdGhlIElEIGluIHRoYXQgYWlycG9ydCBpcyBub3QgdGhlIHNhbWUsIHdoaWNoIG1lYW5zIHRoaXMgYWlycG9ydCBpcyByZWNlaXZpbmcgbmV3IHRvdXJpc3QgZXZlcnkgaG91ci4gVGhlcmUgaXMgbm8gcmVjb3JkIGluIHRoZSBldmVuaW5nIGF0IHRoZSBhaXJwb3J0LCBtYXliZSBpdCBpcyBkdWUgdG8gcGVvcGxlIHdobyBhcnJpdmUgaW4gTW9zY293IGF0IG5pZ2h0IHdpbGwgbm90IGdvIHRvIHRoZSBsYW5kbWFya3MsIHByb2JhYmx5IGdvIHN0cmFpZ2h0IHRvIHRoZWlyIGhvdGVscy4gICANCg0KTW9zdCBvZiB0aGUgaW50ZXJuZXQgcmVjb3JkcyBhcmUgY2x1c3RlcmVkIGF0IHRoZSBjZW50ZXIgb2YgTW9zY293LCB0aGUgYXJlYSBhcm91bmQgS3JlbWxpbiBhbmQgUmVkIFNxdWFyZSBldGMuIFRoaXMgc2hvd3MgdGhhdCBubyBtYXR0ZXIgd2hhdCBwbGFjZSBwZW9wbGUgdmlzaXQgaW4gTW9zY293LCB0aGUgbGFuZG1hcmtzIGF0IHRoZSBjZW50cmFsIE1vc2NvdyBhcmUgdGhlIG11c3QtdmlzaXRlZCBwbGFjZXMgZm9yIG1vc3Qgb2YgdGhlIHRvdXJpc3RzIHRvIE1vc2Nvdy4gICANCg0KQWxzbywgd2Ugbm90aWNlIHRoYXQgbWFueSBvZiB0aGUgY2x1c3RlciBvZiBpbnRlcm5ldCByZXF1ZXN0IGlzIG9uIGEgYnJpZGdlIG9yIGF0IHRoZSB3YXRlcmZyb250LCB0aGlzIG1heSBiZSBkdWUgdG8gdGhlIGJyaWRnZSBhbmQgd2F0ZXJmcm9udCBhcmUgZ3JlYXQgcGxhY2VzIGZvciBwaG90b2dyYXBoeSwgcGVvcGxlIG1heSB0YWtlIHBob3RvcyB0aGVyZSB1c2luZyB0aGVpciBtb2JpbGUgcGhvbmVzLCBhbmQgdGhlbiB1cGxvYWQgb250byB0aGUgc29jaWFsIG1lZGlhLCB3aGljaCByZXF1aXJlcyBpbnRlcm5ldCByZXF1ZXN0LiAgIA0KDQpOb3csIHdlIHRha2UgYSBsb29rIGF0IHRoZSBhaXJwb3J0cyBmcm9tIHdoZXJlIG91ciB0b3VyaXN0cyBjb21lLiBJdCBpcyBhIGxpdHRsZSBiaXQgc3VycHJpc2VkIHRoYXQgcGVvcGxlIHZpc2l0aW5nIFN0LiBCYXNpbOKAmXMgQ2F0aGVkcmFsIGFsbCBjb21lIGZyb20gVm51a292byBJbnRlcm5hdGlvbmFsIEFpcnBvcnQsIHNpbmNlIFNoZXJlbWV0eWV2byBJbnRlcm5hdGlvbmFsIEFpcnBvcnQgaGFuZGxlcyBhcyB0d2ljZSBhcyBtYW55IHBhc3NlbmdlcnMgdGhhbiBpdC4gIFNpbWlsYXIgc2l0dWF0aW9uIGhhcHBlbnMgdG8gdG91cmlzdCB3aG8gdmlzaXRlZCBHVU0gRGVwYXJ0bWVudCBTdG9yZSAoYWthLiBHbGF2bnkgVW5pdmVyYWxueSBNYWdhemluKSwgd2l0aCBvbmx5IDcgcmVjb3JkcyBvY2N1ciBpbiBTaGVyZW1ldHlldm8gSW50ZXJuYXRpb25hbCBBaXJwb3J0LiBBbm90aGVyIHNpZ25pZmljYW50IGZpbmRpbmcgaXMgdGhhdCB0aGVyZSBpcyBubyBJbnRlcm5ldCB1c2FnZSByZWNvcmQgaW4gYW55IGFpcnBvcnRzIGZyb20gcGVvcGxlIHdobyB2aXNpdCBQYXRyaWFyY2jigJlzIFBvbmQuIEl0IGlzIHBvc3NpYmxlIHRoYXQgdGhleSBhcmUgYWxsIGxvY2FsIGNpdGl6ZW5zIHdobyBqdXN0IGdvIHRvIHRoZSBwb25kIGZvciBhIHdhbGsgaW5zdGVhZCBvZiB0b3VyaXN0cy4gQWZ0ZXIgYWxsLCBpdCBpcyBub3QgYSBoaXN0b3JpY2FsIGFyY2hpdGVjdHVyZSB5b3UgY291bGQgbm90IGZpbmQgYW55d2hlcmUgb3RoZXIgdGhhbiBNb3Njb3cgb3IgYSBtdXN0LWdvLXRvIGluIFJ1c3NpYS4gQXMgZm9yIEJvbHNob2kgVGhlYXRyZSBhbmQgTW9zY293IE1ldHJvLCB0aGVyZSBpcyBubyBub3RpY2VhYmxlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgbnVtYmVycyBvZiByZWNvcmRzIGluIGJvdGggYWlycG9ydHMuDQoNCg0KIzYgQ29uY2x1c2lvbg0KVGhlcmUgbWF5IGJlIHNvbWUgbGltaXRhdGlvbnMgaW4gdGhpcyBwcm9qZWN0LiBGaXJzdCwgdGhlIGRhdGEgaXMgdGhlIG1vYmlsZSBpbnRlcm5ldCByZXF1ZXN0IGRhdGEgZnJvbSBvbmUgY2FycmllciBpbiBNaWRlYXN0IGFuZCBSdXNzaWEsIHdlIGRvIG5vdCBrbm93IHdoZXRoZXIgdGhlIHVzZXIgb2YgdGhpcyBjYXJyaWVyIGNhbiByZXByZXNlbnQgYWxsIHRoZSBwZW9wbGUgaW4gdGhhdCBjb3VudHJ5LCBhcyB0aGVyZSBtaWdodCBiZSBzeXN0ZW1hdGljIGJpYXMgaW4gdGhlIHNhbXBsZSwgc2F5LCBwb29yIHBlb3BsZSB0ZW5kIHRvIHVzZSBjaGVhcGVyIGNhcnJpZXIuIE1heWJlIHdlIHNob3VsZCBjb2xsZWN0IG1vcmUgaW5mb3JtYXRpb24gYWJvdXQgdGhpcyBjYXJyaWVyIGFuZCB0aGUgdXNlcnPigJkgY2hhcmFjdGVyaXN0aWNzIG9mIHRoZSBjYXJyaWVyIHRvIG1ha2UgYSBmdXJ0aGVyIGRpc2N1c3Npb24uDQoNClNlY29uZCwgd2UgdXNlIHRoZSBudW1iZXIgb2YgcmVxdWVzdCByZWNvcmRzIGluIG91ciBhbmFseXNpcywgd2hpY2ggbWlnaHQgcmV2ZWFsIHNvbWUgaW1wb3J0YW50IGluZm9ybWF0aW9uIGluIHRoZSBkYXRhIHNldC4gSW4gdGhlIGFuYWx5c2lzIG9mIHBvcHVsYXRpb24gYW5kIEdEUCBvZiBNaWRlYXN0IGNvdW50cmllcywgSSBoYXZlIG1lbnRpb25lZCBzb21lIGFsdGVybmF0aXZlIHdheXMgdGhhdCBjYW4gdXNlIHVuaXF1ZSBJRHMgdG8gZG8gdGhlIGFuYWx5c2lzLiBGb3IgdGhlIGludGVybmV0IHJlcXVlc3QgbW90aW9uIGluIE1vc2NvdyBwYXJ0LCB3ZSBjYW4gYWxzbyB1c2UgdGhlIHVuaXF1ZSBJRHMgdG8gdmlzdWFsaXplIHRoZSBtb3Rpb24gb2YgcGVvcGxlIHJhdGhlciB0aGFuIGludGVybmV0IHJlcXVlc3QsIGhvd2V2ZXIsIGEgcGVyc29uIG1heSBoYXZlIG1hbnkgcmVxdWVzdHMgaW4gbWFueSBwbGFjZXMgZHVyaW5nIG9uZSBob3VyLCBpdCBpcyBoYXJkIHRvIGRldGVybWluZSB3aGljaCBwb2ludCB3ZSBzaG91bGQgY2hvb3NlLiBCZXNpZGVzLCB0aGUgZGF0YSBpcyBvbmx5IGF2YWlsYWJsZSB3aGVuIHBlb3BsZSBtYWRlIGludGVybmV0IHJlcXVlc3QsIHRodXMgaXQgaXMgaGFyZCB0byB0cmFjayBhIHBlcnNvbuKAmXMgbG9jYXRpb24gd2hlbiBoZSBkb2VzIG5vdCBtYWtlIGludGVybmV0IHJlcXVlc3QuIEJ1dCB0aGVzZSBhbHRlcm5hdGl2ZXMgY2FuIGJlIHRoZSBmdXR1cmUgZGlyZWN0aW9ucyB0byB0cnkuDQoNClRoaXJkLCB0aGVyZSBhcmUgYSBmZXcgYnVncyBpbiB0aGUgc2hpbnkgYXBwcy4gV2hlbiB3ZSBwbGF5IHRoZSBhbmltYXRpb24gaW50ZXJhY3RpdmUgbWFwLCB0aGUgYmFja2dyb3VuZCBvZiB0aGUgbWFwIGlzIGFsd2F5cyBmbGFzaGluZyBiZWNhdXNlIGVhY2ggaG91ciBzdGVwIHRoZSBzaGlueSBnZW5lcmF0ZXMgYSBuZXcgbWFwIHVuZGVyIHRoZSBob29kLiBXZSB0cnkgdG8gdXNlIHRoZSBKYXZhU2NyaXB0IHBsdWdpbiBvZiBsZWFmbGV0OiBMZWFmbGV0LnRpbWVsaW5lLCBidXQgaXQgdHVybnMgb3V0IHRvIGhhdmUgZXZlbiBtb3JlIGJ1Z3MgdGhhbiBzaGlueSwgc28gd2UgZmluYWxseSBjaG9vc2UgdG8gdXNlIFNoaW55J3Mgb3duIHNsaWRlciBzZWxlY3Rvci4gQWxzbywgdGhlIHNsaWRlciBzZWxlY3RvcnMgb2YgdGhlIHR3byBtYXBzIGlzIGhhcmQgdG8gZHJhZywgYW5kIHRoZSBoYXJkbmVzcyBpcyBkaWZmZXJlbnQgb24gZGlmZmVyZW50IGdyb3VwIG1lbWJlcidzIGNvbXB1dGVyLiBXZSB0aGluayB0aGlzIG1pZ2h0IGJlIGEgYnVnIG9mIHNoaW55IGl0c2VsZi4NCg0KQXMgZmFyIGFzIHRoZSBsZXNzb24gbGVhcm5lZCwgd2UgY291bGQgaGF2ZSBkb25lIGJldHRlciBpbiBleHBsb3JpbmcgdGhlIGRlZXAgbWVhbmluZyBvciBwYXR0ZXJucyBvZiB0aGUgZGF0YS4gSW5zdGVhZCwgd2Ugc3BlbnQgdG9ucyBvZiBob3VycyB0cnlpbmcgdG8gZGVidWcgdGhlc2UgYnVncyBpbiBzaGlueSBhbmQgamF2YXNjcmlwdCwgb3IgdGhlIG1vcmUgYmVhdGlmdWwgd2F5IHRvIHZpc3VhbGl6ZSBvdXIgbWFwcyB1c2luZyBTaGlueS4gSXQgd2FzIHJlYWxseSB0aW1lLWNvbnN1bWluZyBhbmQgaGF2ZSB0aGUgbGVhc3QgbWFyZ2luYWwgYmVuaWZpdCwgYW5kIGRyaWZ0ZWQgdXMgZnJvbSBhbmFseXppbmcgdGhlIGRhdGEgZGVlcGVyIGFuZCBkaXNjb3ZlcmluZyBwb3NzaWJsZSByZXNhb25zIG9yIHN0b3JpZXMgYmVoaW5kIHRoZXNlIGZpbmRpbmdzLg==